AaveLiquidation

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "contracts/aaveliquidationdemoEth.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.17;\r
\r
/**\r
 * @title AaveLiquidationDemo\r
 * @notice Educational contract demonstrating Aave V3 liquidation functionality\r
 * @dev This contract shows how to liquidate underwater positions on Aave V3\r
 * \r
 * ETHEREUM MAINNET ADDRESSES:\r
 * - Aave V3 Pool Addresses Provider: 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e\r
 * - Aave V3 Pool Data Provider: 0x7B4EB56E7CD4b454BA8ff71E4518426369a138a3\r
 * - WETH: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2\r
 * - USDC: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48\r
 * - USDT: 0xdAC17F958D2ee523a2206206994597C13D831ec7\r
 * - DAI: 0x6B175474E89094C44Da98b954EedeAC495271d0F\r
 * - WBTC: 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599\r
 * - LINK: 0x514910771AF9Ca656af840dff83E8264EcF986CA\r
 * - AAVE: 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9\r
 * \r
 * HOW LIQUIDATION WORKS:\r
 * 1. User borrows assets using collateral (e.g., deposits ETH, borrows USDC)\r
 * 2. If collateral value drops, health factor < 1.0 (underwater)\r
 * 3. Liquidator repays part of debt and receives collateral + bonus\r
 * 4. Liquidator profits from the liquidation bonus (typically 5%)\r
 * \r
 * HOW TO USE:\r
 * 1. Deploy contract (no constructor parameters needed)\r
 * 2. Fund contract with debt token (e.g., USDC to repay user's debt)\r
 * 3. Find underwater user (health factor < 1.0)\r
 * 4. Call liquidateUser() with appropriate parameters\r
 * 5. Receive collateral tokens (more than debt repaid due to bonus)\r
 * 6. Withdraw received collateral using withdrawToken()\r
 */\r
\r
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";\r
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";\r
import {IPoolAddressesProvider} from "@aave/core-v3/contracts/interfaces/IPoolAddressesProvider.sol";\r
import {IPool} from "@aave/core-v3/contracts/interfaces/IPool.sol";\r
import {IPoolDataProvider} from "@aave/core-v3/contracts/interfaces/IPoolDataProvider.sol";\r
\r
contract AaveLiquidation {\r
    using SafeERC20 for IERC20;\r
    \r
    // ========== STATE VARIABLES ==========\r
    \r
    address public owner;\r
    IPool public immutable POOL;\r
    IPoolDataProvider public immutable dataProvider;\r
    address public poolAddressesProvider;\r
    \r
    // ETHEREUM MAINNET addresses\r
    address public constant POOL_ADDRESSES_PROVIDER = 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e;\r
    address public constant DATA_PROVIDER = 0x7B4EB56E7CD4b454BA8ff71E4518426369a138a3;\r
    \r
    \r
    // ========== EVENTS ==========\r
    \r
    /**\r
     * @notice Emitted when a liquidation is executed successfully\r
     * @param user Address of the liquidated user\r
     * @param debtAsset Asset that was repaid\r
     * @param collateralAsset Asset that was received\r
     * @param debtToCover Amount of debt repaid\r
     * @param liquidatedCollateralAmount Amount of collateral received\r
     */\r
    event LiquidationExecuted(\r
        address indexed user,\r
        address indexed debtAsset,\r
        address indexed collateralAsset,\r
        uint256 debtToCover,\r
        uint256 liquidatedCollateralAmount\r
    );\r
    \r
    /**\r
     * @notice Emitted when tokens are withdrawn from contract\r
     * @param token Address of token withdrawn\r
     * @param to Recipient address\r
     * @param amount Amount withdrawn\r
     */\r
    event TokensWithdrawn(\r
        address indexed token,\r
        address indexed to,\r
        uint256 amount\r
    );\r
    \r
    /**\r
     * @notice Emitted for debugging and educational purposes\r
     * @param message Description of the step\r
     * @param value1 First numeric value\r
     * @param value2 Second numeric value\r
     */\r
    event DebugInfo(string message, uint256 value1, uint256 value2);\r
    \r
    \r
    // ========== CONSTRUCTOR ==========\r
    \r
    /**\r
     * @notice Initialize the liquidation demo contract\r
     * @dev Uses Pool Addresses Provider to get the actual Pool address (same pattern as FlashLoanSimpleReceiverBase)\r
     */\r
    constructor() {\r
        owner = msg.sender;\r
        poolAddressesProvider = POOL_ADDRESSES_PROVIDER;\r
        \r
        // Get the actual Pool address from the Provider (same as flashloan contract)\r
        IPoolAddressesProvider provider = IPoolAddressesProvider(POOL_ADDRESSES_PROVIDER);\r
        POOL = IPool(provider.getPool());\r
        \r
        dataProvider = IPoolDataProvider(DATA_PROVIDER);\r
    }\r
    \r
    \r
    // ========== MODIFIERS ==========\r
    \r
    modifier onlyOwner() {\r
        require(msg.sender == owner, "Only owner can call this function");\r
        _;\r
    }\r
    \r
    \r
    // ========== MAIN LIQUIDATION FUNCTION ==========\r
    \r
    /**\r
     * @notice Execute a liquidation on an underwater Aave position\r
     * @dev This is the core liquidation function - study this carefully!\r
     * \r
     * @param user Address of the user to liquidate (must have health factor < 1.0)\r
     * @param debtAsset Address of the debt token to repay (e.g., USDC they borrowed)\r
     * @param collateralAsset Address of the collateral to receive (e.g., WETH they deposited)\r
     * @param debtToCover Amount of debt to repay (in debt asset units)\r
     *        SPECIAL: Use type(uint256).max to let Aave calculate max safe amount automatically\r
     * @param receiveAToken If true, receive aToken; if false, receive underlying token\r
     * @return liquidatedCollateralAmount Amount of collateral received\r
     * \r
     * REQUIREMENTS:\r
     * - User's health factor must be < 1.0 (underwater)\r
     * - Contract must have enough debtAsset to repay\r
     * - debtToCover cannot exceed max liquidation amount (typically 50% of debt)\r
     * \r
     * EXAMPLE USAGE (Liquidate USDC debt, receive WETH collateral):\r
     * - user: 0x123... (found using monitoring scripts)\r
     * - debtAsset: 0x94a9D9AC8a22534E3FaCa9F4e7F2E2cf85d5E4C8 (USDC)\r
     * - collateralAsset: 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14 (WETH)\r
     * - debtToCover: 1000000000 (1000 USDC - 6 decimals)\r
     *   OR: 115792089237316195423570985008687907853269984665640564039457584007913129639935 (max uint256 - auto calculation)\r
     * - receiveAToken: false (receive actual WETH, not aWETH)\r
     * \r
     * HOW IT WORKS:\r
     * 1. Contract approves Aave to spend debtAsset\r
     * 2. Calls Aave's liquidationCall function\r
     * 3. Aave transfers debtAsset from contract to user's debt position\r
     * 4. Aave transfers collateralAsset from user to contract (with liquidation bonus)\r
     * 5. Contract now has more value than it spent (profit = liquidation bonus)\r
     * \r
     * LIQUIDATION BONUS:\r
     * - Typically 5% (varies by asset)\r
     * - If you repay 1000 USDC debt, you might receive $1050 worth of collateral\r
     * - This is your profit for performing the liquidation\r
     * \r
     * PRO TIP FOR EDGE CASES:\r
     * - When health factor is very close to 1.0 (e.g., 0.96-0.99), use type(uint256).max\r
     * - Aave will automatically calculate the maximum safe liquidation amount\r
     * - This prevents error "25" when manually calculated amounts are rejected\r
     */\r
    function liquidateUser(\r
        address user,\r
        address debtAsset,\r
        address collateralAsset,\r
        uint256 debtToCover,\r
        bool receiveAToken\r
    ) external onlyOwner returns (uint256 liquidatedCollateralAmount) {\r
        // ===== STEP 1: VALIDATE INPUTS =====\r
        require(user != address(0), "Invalid user address");\r
        require(debtAsset != address(0), "Invalid debt asset");\r
        require(collateralAsset != address(0), "Invalid collateral asset");\r
        require(debtToCover > 0, "Debt to cover must be > 0");\r
        \r
        emit DebugInfo("Starting liquidation", debtToCover, 0);\r
        \r
        // ===== STEP 2: CHECK USER'S HEALTH FACTOR =====\r
        // Health factor < 1e18 means position is underwater (liquidatable)\r
        (, , , , , uint256 healthFactor) = POOL.getUserAccountData(user);\r
        require(healthFactor < 1e18, "User health factor is healthy (>= 1.0)");\r
        \r
        emit DebugInfo("User health factor", healthFactor, 1e18);\r
        \r
        // ===== STEP 3: CHECK CONTRACT HAS ENOUGH DEBT ASSET =====\r
        uint256 contractBalance = IERC20(debtAsset).balanceOf(address(this));\r
        // Skip balance check if using max uint256 (Aave will calculate actual amount needed)\r
        // if (debtToCover != type(uint256).max) {\r
            require(contractBalance >= debtToCover, "Insufficient debt asset in contract");\r
        // } else {\r
            // require(contractBalance > 0, "Contract has no debt asset for liquidation");\r
        // }\r
        \r
        emit DebugInfo("Contract balance", contractBalance, debtToCover);\r
        \r
        // ===== STEP 4: CHECK COLLATERAL BALANCE BEFORE =====\r
        // Track collateral balance before liquidation\r
        uint256 collateralBefore = IERC20(collateralAsset).balanceOf(address(this));\r
        // emit DebugInfo("Collateral before liquidation", collateralBefore, 0);\r
        \r
        // ===== STEP 5: APPROVE AAVE TO SPEND DEBT ASSET =====\r
        // Aave needs permission to transfer debtAsset from this contract\r
        // CRITICAL: Approve the FULL contract balance, not just debtToCover\r
        // This matches the pattern in the working flashloan contract\r
        // Aave's internal liquidation logic may need extra approval for calculations\r
        // IERC20(debtAsset).approve(address(POOL), 0);\r
        // IERC20(debtAsset).approve(address(POOL), type(uint256).max);\r
\r
        // uint256 amountToApprove = debtToCover == type(uint256).max ? debtToCover : contractBalance;\r
\r
        // // Reset to 0 first for USDT-style tokens\r
        // IERC20(debtAsset).approve(address(POOL), 0);\r
        IERC20(debtAsset).approve(address(POOL), debtToCover);\r
        // IERC20(debtAsset).approve(address(POOL), contractBalance);\r
        emit DebugInfo("Approved Aave Pool", contractBalance, debtToCover);\r
        \r
        // ===== STEP 6: EXECUTE LIQUIDATION =====\r
        /**\r
         * liquidationCall parameters explained:\r
         * \r
         * @param collateralAsset - The collateral you want to receive\r
         * @param debtAsset - The debt you're repaying\r
         * @param user - The underwater user you're liquidating\r
         * @param debtToCover - How much debt to repay\r
         * @param receiveAToken - Whether to receive aToken or underlying token\r
         * \r
         * What happens inside Aave:\r
         * 1. Validates health factor < 1.0\r
         * 2. Calculates max liquidation amount (typically 50% of debt)\r
         * 3. Transfers debtAsset from liquidator to user's debt position\r
         * 4. Calculates collateral to give (debt value + liquidation bonus)\r
         * 5. Transfers collateral from user's position to liquidator\r
         * 6. Updates user's debt and collateral balances\r
         */\r
        POOL.liquidationCall(\r
            collateralAsset,    // What we want to receive\r
            debtAsset,          // What we're repaying\r
            user,               // Who we're liquidating\r
            debtToCover,        // How much debt we're covering\r
            receiveAToken       // Receive aToken or underlying?\r
        );\r
        \r
        emit DebugInfo("Liquidation call completed", 1, 0);\r
        \r
        // ===== STEP 7: CHECK HOW MUCH COLLATERAL WE RECEIVED =====\r
        uint256 collateralAfter = IERC20(collateralAsset).balanceOf(address(this));\r
        \r
        // Safe arithmetic: prevent underflow\r
        require(collateralAfter >= collateralBefore, "Collateral balance decreased unexpectedly");\r
        liquidatedCollateralAmount = collateralAfter - collateralBefore;\r
        \r
        // emit DebugInfo("Collateral received", liquidatedCollateralAmount, collateralAfter);\r
        \r
        // ===== STEP 8: VERIFY WE RECEIVED COLLATERAL =====\r
        require(liquidatedCollateralAmount > 0, "No collateral received from liquidation");\r
        \r
        // ===== STEP 9: EMIT SUCCESS EVENT =====\r
        // emit LiquidationExecuted(\r
        //     user,\r
        //     debtAsset,\r
        //     collateralAsset,\r
        //     debtToCover,\r
        //     liquidatedCollateralAmount\r
        // );\r
        \r
        return liquidatedCollateralAmount;\r
    }\r
    \r
    \r
    // ========== VIEW FUNCTIONS (FOR ANALYSIS) ==========\r
    \r
    /**\r
     * @notice Get detailed information about a user's Aave position\r
     * @dev Use this to check if a user is liquidatable BEFORE attempting liquidation\r
     * \r
     * @param user Address of the user to check\r
     * @return totalCollateralBase Total collateral in base currency (USD, 8 decimals)\r
     * @return totalDebtBase Total debt in base currency (USD, 8 decimals)\r
     * @return availableBorrowsBase Available borrow capacity (USD, 8 decimals)\r
     * @return currentLiquidationThreshold Liquidation threshold (percentage, 4 decimals)\r
     * @return ltv Loan-to-value ratio (percentage, 4 decimals)\r
     * @return healthFactor Health factor (18 decimals) - < 1e18 means liquidatable\r
     * \r
     * HEALTH FACTOR EXPLAINED:\r
     * - Health Factor = (Collateral * Liquidation Threshold) / Total Debt\r
     * - 1.5e18 = Healthy (150% collateralized)\r
     * - 1.0e18 = At liquidation threshold\r
     * - 0.9e18 = Underwater! Can be liquidated\r
     * - If health factor < 1.0, position can be liquidated\r
     * \r
     * EXAMPLE:\r
     * - User deposits $1500 ETH (liquidation threshold = 80%)\r
     * - User borrows $1000 USDC\r
     * - Health Factor = (1500 * 0.80) / 1000 = 1.2 (Healthy)\r
     * - If ETH drops to $1250:\r
     * - Health Factor = (1250 * 0.80) / 1000 = 1.0 (At threshold)\r
     * - If ETH drops to $1000:\r
     * - Health Factor = (1000 * 0.80) / 1000 = 0.8 (LIQUIDATABLE!)\r
     */\r
    function getUserAccountData(address user) external view returns (\r
        uint256 totalCollateralBase,\r
        uint256 totalDebtBase,\r
        uint256 availableBorrowsBase,\r
        uint256 currentLiquidationThreshold,\r
        uint256 ltv,\r
        uint256 healthFactor\r
    ) {\r
        return POOL.getUserAccountData(user);\r
    }\r
    \r
    /**\r
     * @notice Check if a specific user position is liquidatable\r
     * @param user Address of user to check\r
     * @return isLiquidatable True if health factor < 1.0\r
     * @return healthFactor Current health factor (18 decimals)\r
     */\r
    function isUserLiquidatable(address user) external view returns (\r
        bool isLiquidatable,\r
        uint256 healthFactor\r
    ) {\r
        (, , , , , healthFactor) = POOL.getUserAccountData(user);\r
        isLiquidatable = healthFactor < 1e18;\r
    }\r
    \r
    /**\r
     * @notice Get user's debt for a specific asset\r
     * @param user Address of user\r
     * @param asset Address of debt asset (e.g., USDC)\r
     * @return currentVariableDebt Amount of variable rate debt\r
     * \r
     * USE THIS to determine how much debt you can repay in liquidation\r
     * Note: You can typically liquidate up to 50% of user's debt in one transaction\r
     */\r
    function getUserDebt(address user, address asset) external view returns (\r
        uint256 currentVariableDebt\r
    ) {\r
        (, , currentVariableDebt, , , , , , ) = dataProvider.getUserReserveData(asset, user);\r
    }\r
    \r
    /**\r
     * @notice Get user's collateral for a specific asset\r
     * @param user Address of user\r
     * @param asset Address of collateral asset (e.g., WETH)\r
     * @return currentATokenBalance Amount of collateral deposited (in aToken)\r
     */\r
    function getUserCollateral(address user, address asset) external view returns (\r
        uint256 currentATokenBalance\r
    ) {\r
        (currentATokenBalance, , , , , , , , ) = dataProvider.getUserReserveData(asset, user);\r
    }\r
    \r
    /**\r
     * @notice Get liquidation bonus for an asset\r
     * @param asset Address of the asset\r
     * @return liquidationBonus Liquidation bonus in basis points (10000 = 100%)\r
     * \r
     * EXAMPLE:\r
     * - If liquidationBonus = 10500, bonus is 5% (105%)\r
     * - If you repay 1000 USDC, you receive $1050 worth of collateral\r
     */\r
    function getLiquidationBonus(address asset) external view returns (\r
        uint256 liquidationBonus\r
    ) {\r
        (, , liquidationBonus, , , , , , , ) = dataProvider.getReserveConfigurationData(asset);\r
    }\r
    \r
    \r
    // ========== HELPER FUNCTIONS ==========\r
    \r
    /**\r
     * @notice Get balance of any token held by this contract\r
     * @param token Address of token to check\r
     * @return balance Token balance\r
     */\r
    function getTokenBalance(address token) external view returns (uint256) {\r
        return IERC20(token).balanceOf(address(this));\r
    }\r
    \r
    /**\r
     * @notice Withdraw tokens from contract\r
     * @param token Address of token to withdraw\r
     * @param amount Amount to withdraw (0 = withdraw all)\r
     */\r
    function withdrawToken(address token, uint256 amount) external onlyOwner {\r
        if (amount == 0) {\r
            amount = IERC20(token).balanceOf(address(this));\r
        }\r
        require(amount > 0, "No tokens to withdraw");\r
        \r
        IERC20(token).safeTransfer(owner, amount);\r
        emit TokensWithdrawn(token, owner, amount);\r
    }\r
    \r
    /**\r
     * @notice Withdraw ETH from contract\r
     * @param amount Amount to withdraw (0 = withdraw all)\r
     */\r
    function withdrawETH(uint256 amount) external onlyOwner {\r
        if (amount == 0) {\r
            amount = address(this).balance;\r
        }\r
        require(amount > 0, "No ETH to withdraw");\r
        \r
        payable(owner).transfer(amount);\r
    }\r
    \r
    /**\r
     * @notice Allow contract to receive ETH\r
     */\r
    receive() external payable {}\r
    \r
    \r
    // ========== VIEW FUNCTIONS FOR CONTRACT INFO ==========\r
    \r
    /**\r
     * @notice Get contract configuration\r
     * @return _owner Owner address\r
     * @return _pool Aave Pool address\r
     * @return _dataProvider Data Provider address\r
     */\r
    function getContractInfo() external view returns (\r
        address _owner,\r
        address _pool,\r
        address _dataProvider\r
    ) {\r
        return (owner, address(POOL), address(dataProvider));\r
    }\r
}\r
\r
\r
/**\r
 * ============================================\r
 * STEP-BY-STEP USAGE GUIDE FOR REMIX\r
 * ============================================\r
 * \r
 * 1. COMPILE THE CONTRACT\r
 *    - Open Remix IDE (remix.ethereum.org)\r
 *    - Create new file: AaveLiquidationDemo.sol\r
 *    - Paste this code\r
 *    - Compiler: Select 0.8.17 or higher\r
 *    - Click "Compile AaveLiquidationDemo.sol"\r
 * \r
 * 2. DEPLOY TO SEPOLIA\r
 *    - Switch MetaMask to Sepolia network\r
 *    - In Remix Deploy tab, select "Injected Provider - MetaMask"\r
 *    - No constructor parameters needed!\r
 *    - Click "Deploy"\r
 *    - Confirm transaction in MetaMask\r
 *    - Copy deployed contract address\r
 * \r
 * 3. FIND A LIQUIDATABLE USER\r
 *    Option A - Use your monitoring script:\r
 *    - Run: node monitorBorrowersHF.js\r
 *    - Look for users with health factor < 1.0\r
 *    - Copy their address\r
 * \r
 *    Option B - Check manually in Remix:\r
 *    - Call: getUserAccountData(USER_ADDRESS)\r
 *    - Check healthFactor value\r
 *    - If < 1000000000000000000 (1e18), user is liquidatable\r
 * \r
 * 4. ANALYZE THE TARGET USER\r
 *    - Call: getUserDebt(USER_ADDRESS, USDC_ADDRESS)\r
 *      → Shows how much USDC they owe\r
 *    - Call: getUserCollateral(USER_ADDRESS, WETH_ADDRESS)\r
 *      → Shows how much WETH they deposited\r
 *    - Call: getLiquidationBonus(WETH_ADDRESS)\r
 *      → Shows bonus you'll receive (e.g., 10500 = 5% bonus)\r
 * \r
 * 5. FUND CONTRACT WITH DEBT ASSET\r
 *    - If liquidating USDC debt, send USDC to contract\r
 *    - Amount: At least the debtToCover amount\r
 *    - Example: Send 1000 USDC to contract address\r
 *    - Verify: Call getTokenBalance(USDC_ADDRESS)\r
 * \r
 * 6. EXECUTE LIQUIDATION\r
 *    - Call: liquidateUser with parameters:\r
 *      user: 0x... (underwater user address)\r
 *      debtAsset: 0x94a9D9AC8a22534E3FaCa9F4e7F2E2cf85d5E4C8 (USDC)\r
 *      collateralAsset: 0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14 (WETH)\r
 *      debtToCover: 1000000000 (1000 USDC with 6 decimals)\r
 *      receiveAToken: false\r
 *    - Confirm in MetaMask\r
 *    - Wait for transaction confirmation\r
 * \r
 * 7. CHECK YOUR PROFIT\r
 *    - Call: getTokenBalance(WETH_ADDRESS)\r
 *    - You should have received WETH worth more than the USDC you spent\r
 *    - The difference is your profit from the liquidation bonus!\r
 * \r
 * 8. WITHDRAW YOUR PROFIT\r
 *    - Call: withdrawToken(WETH_ADDRESS, 0)\r
 *    - WETH will be sent to your wallet\r
 * \r
 * ============================================\r
 * UNDERSTANDING LIQUIDATION ECONOMICS\r
 * ============================================\r
 * \r
 * EXAMPLE SCENARIO:\r
 * ----------------\r
 * User Position:\r
 * - Deposited: 1 WETH ($3000)\r
 * - Borrowed: 2000 USDC\r
 * - Liquidation Threshold: 80%\r
 * - Health Factor: (3000 * 0.80) / 2000 = 1.2 (Healthy)\r
 * \r
 * Price Drops:\r
 * - ETH drops to $2400\r
 * - Health Factor: (2400 * 0.80) / 2000 = 0.96 (LIQUIDATABLE!)\r
 * \r
 * Liquidation:\r
 * - You repay: 1000 USDC (50% of debt)\r
 * - Liquidation bonus: 5%\r
 * - Collateral value to receive: 1000 * 1.05 = $1050\r
 * - WETH received: $1050 / $2400 = 0.4375 WETH\r
 * \r
 * Your Profit:\r
 * - Spent: 1000 USDC ($1000)\r
 * - Received: 0.4375 WETH ($1050)\r
 * - Profit: $50 (5% liquidation bonus)\r
 * \r
 * ============================================\r
 * TROUBLESHOOTING\r
 * ============================================\r
 * \r
 * ERROR: "User health factor is healthy"\r
 * → User's health factor >= 1.0, they cannot be liquidated yet\r
 * → Wait for price movement or find different user\r
 * \r
 * ERROR: "Insufficient debt asset in contract"\r
 * → Contract doesn't have enough debt token to repay\r
 * → Transfer more debt token to contract\r
 * \r
 * ERROR: "No collateral received from liquidation"\r
 * → Liquidation failed or user has no collateral\r
 * → Check user actually has collateral deposited\r
 * → Verify addresses are correct\r
 * \r
 * ERROR: Liquidation reverts with no message\r
 * → You might be trying to liquidate more than 50% of debt\r
 * → Reduce debtToCover amount\r
 * → Check user still has enough collateral\r
 * \r
 * ============================================\r
 * KEY LEARNING POINTS\r
 * ============================================\r
 * \r
 * 1. HEALTH FACTOR\r
 *    - Below 1.0 = Liquidatable\r
 *    - Calculated as: (Collateral * LiqThreshold) / Debt\r
 *    - Constantly changes with asset prices\r
 * \r
 * 2. LIQUIDATION LIMITS\r
 *    - Typically can liquidate max 50% of user's debt per tx\r
 *    - Some protocols allow 100% if health factor very low\r
 *    - Check Aave docs for specific limits\r
 * \r
 * 3. LIQUIDATION BONUS\r
 *    - Your profit comes from this bonus\r
 *    - Usually 5% but varies by asset\r
 *    - Higher risk assets = higher bonus\r
 * \r
 * 4. GAS COSTS\r
 *    - Liquidations are expensive (lots of operations)\r
 *    - Must ensure profit > gas costs\r
 *    - On mainnet, need ~$100+ profit to be worthwhile\r
 *    - On testnets, practice without worrying about gas\r
 * \r
 * 5. COMPETITION\r
 *    - On mainnet, bots compete for liquidations\r
 *    - Fastest tx wins\r
 *    - May need flashbots or private mempools\r
 *    - Practice on testnet to understand mechanics first\r
 * \r
 * ============================================\r
 */\r
"
    },
    "@aave/core-v3/contracts/interfaces/IPoolDataProvider.sol": {
      "content": "// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';

/**
 * @title IPoolDataProvider
 * @author Aave
 * @notice Defines the basic interface of a PoolDataProvider
 */
interface IPoolDataProvider {
  struct TokenData {
    string symbol;
    address tokenAddress;
  }

  /**
   * @notice Returns the address for the PoolAddressesProvider contract.
   * @return The address for the PoolAddressesProvider contract
   */
  function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);

  /**
   * @notice Returns the list of the existing reserves in the pool.
   * @dev Handling MKR and ETH in a different way since they do not have standard `symbol` functions.
   * @return The list of reserves, pairs of symbols and addresses
   */
  function getAllReservesTokens() external view returns (TokenData[] memory);

  /**
   * @notice Returns the list of the existing ATokens in the pool.
   * @return The list of ATokens, pairs of symbols and addresses
   */
  function getAllATokens() external view returns (TokenData[] memory);

  /**
   * @notice Returns the configuration data of the reserve
   * @dev Not returning borrow and supply caps for compatibility, nor pause flag
   * @param asset The address of the underlying asset of the reserve
   * @return decimals The number of decimals of the reserve
   * @return ltv The ltv of the reserve
   * @return liquidationThreshold The liquidationThreshold of the reserve
   * @return liquidationBonus The liquidationBonus of the reserve
   * @return reserveFactor The reserveFactor of the reserve
   * @return usageAsCollateralEnabled True if the usage as collateral is enabled, false otherwise
   * @return borrowingEnabled True if borrowing is enabled, false otherwise
   * @return stableBorrowRateEnabled True if stable rate borrowing is enabled, false otherwise
   * @return isActive True if it is active, false otherwise
   * @return isFrozen True if it is frozen, false otherwise
   */
  function getReserveConfigurationData(
    address asset
  )
    external
    view
    returns (
      uint256 decimals,
      uint256 ltv,
      uint256 liquidationThreshold,
      uint256 liquidationBonus,
      uint256 reserveFactor,
      bool usageAsCollateralEnabled,
      bool borrowingEnabled,
      bool stableBorrowRateEnabled,
      bool isActive,
      bool isFrozen
    );

  /**
   * @notice Returns the efficiency mode category of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The eMode id of the reserve
   */
  function getReserveEModeCategory(address asset) external view returns (uint256);

  /**
   * @notice Returns the caps parameters of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return borrowCap The borrow cap of the reserve
   * @return supplyCap The supply cap of the reserve
   */
  function getReserveCaps(
    address asset
  ) external view returns (uint256 borrowCap, uint256 supplyCap);

  /**
   * @notice Returns if the pool is paused
   * @param asset The address of the underlying asset of the reserve
   * @return isPaused True if the pool is paused, false otherwise
   */
  function getPaused(address asset) external view returns (bool isPaused);

  /**
   * @notice Returns the siloed borrowing flag
   * @param asset The address of the underlying asset of the reserve
   * @return True if the asset is siloed for borrowing
   */
  function getSiloedBorrowing(address asset) external view returns (bool);

  /**
   * @notice Returns the protocol fee on the liquidation bonus
   * @param asset The address of the underlying asset of the reserve
   * @return The protocol fee on liquidation
   */
  function getLiquidationProtocolFee(address asset) external view returns (uint256);

  /**
   * @notice Returns the unbacked mint cap of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The unbacked mint cap of the reserve
   */
  function getUnbackedMintCap(address asset) external view returns (uint256);

  /**
   * @notice Returns the debt ceiling of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The debt ceiling of the reserve
   */
  function getDebtCeiling(address asset) external view returns (uint256);

  /**
   * @notice Returns the debt ceiling decimals
   * @return The debt ceiling decimals
   */
  function getDebtCeilingDecimals() external pure returns (uint256);

  /**
   * @notice Returns the reserve data
   * @param asset The address of the underlying asset of the reserve
   * @return unbacked The amount of unbacked tokens
   * @return accruedToTreasuryScaled The scaled amount of tokens accrued to treasury that is to be minted
   * @return totalAToken The total supply of the aToken
   * @return totalStableDebt The total stable debt of the reserve
   * @return totalVariableDebt The total variable debt of the reserve
   * @return liquidityRate The liquidity rate of the reserve
   * @return variableBorrowRate The variable borrow rate of the reserve
   * @return stableBorrowRate The stable borrow rate of the reserve
   * @return averageStableBorrowRate The average stable borrow rate of the reserve
   * @return liquidityIndex The liquidity index of the reserve
   * @return variableBorrowIndex The variable borrow index of the reserve
   * @return lastUpdateTimestamp The timestamp of the last update of the reserve
   */
  function getReserveData(
    address asset
  )
    external
    view
    returns (
      uint256 unbacked,
      uint256 accruedToTreasuryScaled,
      uint256 totalAToken,
      uint256 totalStableDebt,
      uint256 totalVariableDebt,
      uint256 liquidityRate,
      uint256 variableBorrowRate,
      uint256 stableBorrowRate,
      uint256 averageStableBorrowRate,
      uint256 liquidityIndex,
      uint256 variableBorrowIndex,
      uint40 lastUpdateTimestamp
    );

  /**
   * @notice Returns the total supply of aTokens for a given asset
   * @param asset The address of the underlying asset of the reserve
   * @return The total supply of the aToken
   */
  function getATokenTotalSupply(address asset) external view returns (uint256);

  /**
   * @notice Returns the total debt for a given asset
   * @param asset The address of the underlying asset of the reserve
   * @return The total debt for asset
   */
  function getTotalDebt(address asset) external view returns (uint256);

  /**
   * @notice Returns the user data in a reserve
   * @param asset The address of the underlying asset of the reserve
   * @param user The address of the user
   * @return currentATokenBalance The current AToken balance of the user
   * @return currentStableDebt The current stable debt of the user
   * @return currentVariableDebt The current variable debt of the user
   * @return principalStableDebt The principal stable debt of the user
   * @return scaledVariableDebt The scaled variable debt of the user
   * @return stableBorrowRate The stable borrow rate of the user
   * @return liquidityRate The liquidity rate of the reserve
   * @return stableRateLastUpdated The timestamp of the last update of the user stable rate
   * @return usageAsCollateralEnabled True if the user is using the asset as collateral, false
   *         otherwise
   */
  function getUserReserveData(
    address asset,
    address user
  )
    external
    view
    returns (
      uint256 currentATokenBalance,
      uint256 currentStableDebt,
      uint256 currentVariableDebt,
      uint256 principalStableDebt,
      uint256 scaledVariableDebt,
      uint256 stableBorrowRate,
      uint256 liquidityRate,
      uint40 stableRateLastUpdated,
      bool usageAsCollateralEnabled
    );

  /**
   * @notice Returns the token addresses of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return aTokenAddress The AToken address of the reserve
   * @return stableDebtTokenAddress The StableDebtToken address of the reserve
   * @return variableDebtTokenAddress The VariableDebtToken address of the reserve
   */
  function getReserveTokensAddresses(
    address asset
  )
    external
    view
    returns (
      address aTokenAddress,
      address stableDebtTokenAddress,
      address variableDebtTokenAddress
    );

  /**
   * @notice Returns the address of the Interest Rate strategy
   * @param asset The address of the underlying asset of the reserve
   * @return irStrategyAddress The address of the Interest Rate strategy
   */
  function getInterestRateStrategyAddress(
    address asset
  ) external view returns (address irStrategyAddress);

  /**
   * @notice Returns whether the reserve has FlashLoans enabled or disabled
   * @param asset The address of the underlying asset of the reserve
   * @return True if FlashLoans are enabled, false otherwise
   */
  function getFlashLoanEnabled(address asset) external view returns (bool);
}
"
    },
    "@aave/core-v3/contracts/interfaces/IPool.sol": {
      "content": "// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;

import {IPoolAddressesProvider} from './IPoolAddressesProvider.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';

/**
 * @title IPool
 * @author Aave
 * @notice Defines the basic interface for an Aave Pool.
 */
interface IPool {
  /**
   * @dev Emitted on mintUnbacked()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address initiating the supply
   * @param onBehalfOf The beneficiary of the supplied assets, receiving the aTokens
   * @param amount The amount of supplied assets
   * @param referralCode The referral code used
   */
  event MintUnbacked(
    address indexed reserve,
    address user,
    address indexed onBehalfOf,
    uint256 amount,
    uint16 indexed referralCode
  );

  /**
   * @dev Emitted on backUnbacked()
   * @param reserve The address of the underlying asset of the reserve
   * @param backer The address paying for the backing
   * @param amount The amount added as backing
   * @param fee The amount paid in fees
   */
  event BackUnbacked(address indexed reserve, address indexed backer, uint256 amount, uint256 fee);

  /**
   * @dev Emitted on supply()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address initiating the supply
   * @param onBehalfOf The beneficiary of the supply, receiving the aTokens
   * @param amount The amount supplied
   * @param referralCode The referral code used
   */
  event Supply(
    address indexed reserve,
    address user,
    address indexed onBehalfOf,
    uint256 amount,
    uint16 indexed referralCode
  );

  /**
   * @dev Emitted on withdraw()
   * @param reserve The address of the underlying asset being withdrawn
   * @param user The address initiating the withdrawal, owner of aTokens
   * @param to The address that will receive the underlying
   * @param amount The amount to be withdrawn
   */
  event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);

  /**
   * @dev Emitted on borrow() and flashLoan() when debt needs to be opened
   * @param reserve The address of the underlying asset being borrowed
   * @param user The address of the user initiating the borrow(), receiving the funds on borrow() or just
   * initiator of the transaction on flashLoan()
   * @param onBehalfOf The address that will be getting the debt
   * @param amount The amount borrowed out
   * @param interestRateMode The rate mode: 1 for Stable, 2 for Variable
   * @param borrowRate The numeric rate at which the user has borrowed, expressed in ray
   * @param referralCode The referral code used
   */
  event Borrow(
    address indexed reserve,
    address user,
    address indexed onBehalfOf,
    uint256 amount,
    DataTypes.InterestRateMode interestRateMode,
    uint256 borrowRate,
    uint16 indexed referralCode
  );

  /**
   * @dev Emitted on repay()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The beneficiary of the repayment, getting his debt reduced
   * @param repayer The address of the user initiating the repay(), providing the funds
   * @param amount The amount repaid
   * @param useATokens True if the repayment is done using aTokens, `false` if done with underlying asset directly
   */
  event Repay(
    address indexed reserve,
    address indexed user,
    address indexed repayer,
    uint256 amount,
    bool useATokens
  );

  /**
   * @dev Emitted on swapBorrowRateMode()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address of the user swapping his rate mode
   * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable
   */
  event SwapBorrowRateMode(
    address indexed reserve,
    address indexed user,
    DataTypes.InterestRateMode interestRateMode
  );

  /**
   * @dev Emitted on borrow(), repay() and liquidationCall() when using isolated assets
   * @param asset The address of the underlying asset of the reserve
   * @param totalDebt The total isolation mode debt for the reserve
   */
  event IsolationModeTotalDebtUpdated(address indexed asset, uint256 totalDebt);

  /**
   * @dev Emitted when the user selects a certain asset category for eMode
   * @param user The address of the user
   * @param categoryId The category id
   */
  event UserEModeSet(address indexed user, uint8 categoryId);

  /**
   * @dev Emitted on setUserUseReserveAsCollateral()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address of the user enabling the usage as collateral
   */
  event ReserveUsedAsCollateralEnabled(address indexed reserve, address indexed user);

  /**
   * @dev Emitted on setUserUseReserveAsCollateral()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address of the user enabling the usage as collateral
   */
  event ReserveUsedAsCollateralDisabled(address indexed reserve, address indexed user);

  /**
   * @dev Emitted on rebalanceStableBorrowRate()
   * @param reserve The address of the underlying asset of the reserve
   * @param user The address of the user for which the rebalance has been executed
   */
  event RebalanceStableBorrowRate(address indexed reserve, address indexed user);

  /**
   * @dev Emitted on flashLoan()
   * @param target The address of the flash loan receiver contract
   * @param initiator The address initiating the flash loan
   * @param asset The address of the asset being flash borrowed
   * @param amount The amount flash borrowed
   * @param interestRateMode The flashloan mode: 0 for regular flashloan, 1 for Stable debt, 2 for Variable debt
   * @param premium The fee flash borrowed
   * @param referralCode The referral code used
   */
  event FlashLoan(
    address indexed target,
    address initiator,
    address indexed asset,
    uint256 amount,
    DataTypes.InterestRateMode interestRateMode,
    uint256 premium,
    uint16 indexed referralCode
  );

  /**
   * @dev Emitted when a borrower is liquidated.
   * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
   * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
   * @param user The address of the borrower getting liquidated
   * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
   * @param liquidatedCollateralAmount The amount of collateral received by the liquidator
   * @param liquidator The address of the liquidator
   * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
   * to receive the underlying collateral asset directly
   */
  event LiquidationCall(
    address indexed collateralAsset,
    address indexed debtAsset,
    address indexed user,
    uint256 debtToCover,
    uint256 liquidatedCollateralAmount,
    address liquidator,
    bool receiveAToken
  );

  /**
   * @dev Emitted when the state of a reserve is updated.
   * @param reserve The address of the underlying asset of the reserve
   * @param liquidityRate The next liquidity rate
   * @param stableBorrowRate The next stable borrow rate
   * @param variableBorrowRate The next variable borrow rate
   * @param liquidityIndex The next liquidity index
   * @param variableBorrowIndex The next variable borrow index
   */
  event ReserveDataUpdated(
    address indexed reserve,
    uint256 liquidityRate,
    uint256 stableBorrowRate,
    uint256 variableBorrowRate,
    uint256 liquidityIndex,
    uint256 variableBorrowIndex
  );

  /**
   * @dev Emitted when the protocol treasury receives minted aTokens from the accrued interest.
   * @param reserve The address of the reserve
   * @param amountMinted The amount minted to the treasury
   */
  event MintedToTreasury(address indexed reserve, uint256 amountMinted);

  /**
   * @notice Mints an `amount` of aTokens to the `onBehalfOf`
   * @param asset The address of the underlying asset to mint
   * @param amount The amount to mint
   * @param onBehalfOf The address that will receive the aTokens
   * @param referralCode 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
   */
  function mintUnbacked(
    address asset,
    uint256 amount,
    address onBehalfOf,
    uint16 referralCode
  ) external;

  /**
   * @notice Back the current unbacked underlying with `amount` and pay `fee`.
   * @param asset The address of the underlying asset to back
   * @param amount The amount to back
   * @param fee The amount paid in fees
   * @return The backed amount
   */
  function backUnbacked(address asset, uint256 amount, uint256 fee) external returns (uint256);

  /**
   * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
   * - E.g. User supplies 100 USDC and gets in return 100 aUSDC
   * @param asset The address of the underlying asset to supply
   * @param amount The amount to be supplied
   * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
   *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
   *   is a different wallet
   * @param referralCode 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
   */
  function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;

  /**
   * @notice Supply with transfer approval of asset to be supplied done via permit function
   * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
   * @param asset The address of the underlying asset to supply
   * @param amount The amount to be supplied
   * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
   *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
   *   is a different wallet
   * @param deadline The deadline timestamp that the permit is valid
   * @param referralCode 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
   * @param permitV The V parameter of ERC712 permit sig
   * @param permitR The R parameter of ERC712 permit sig
   * @param permitS The S parameter of ERC712 permit sig
   */
  function supplyWithPermit(
    address asset,
    uint256 amount,
    address onBehalfOf,
    uint16 referralCode,
    uint256 deadline,
    uint8 permitV,
    bytes32 permitR,
    bytes32 permitS
  ) external;

  /**
   * @notice Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
   * E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
   * @param asset The address of the underlying asset to withdraw
   * @param amount The underlying amount to be withdrawn
   *   - Send the value type(uint256).max in order to withdraw the whole aToken balance
   * @param to The address that will receive the underlying, same as msg.sender if the user
   *   wants to receive it on his own wallet, or a different address if the beneficiary is a
   *   different wallet
   * @return The final amount withdrawn
   */
  function withdraw(address asset, uint256 amount, address to) external returns (uint256);

  /**
   * @notice Allows users to borrow a specific `amount` of the reserve underlying asset, provided that the borrower
   * already supplied enough collateral, or he was given enough allowance by a credit delegator on the
   * corresponding debt token (StableDebtToken or VariableDebtToken)
   * - E.g. User borrows 100 USDC passing as `onBehalfOf` his own address, receiving the 100 USDC in his wallet
   *   and 100 stable/variable debt tokens, depending on the `interestRateMode`
   * @param asset The address of the underlying asset to borrow
   * @param amount The amount to be borrowed
   * @param interestRateMode The interest rate mode at which the user wants to borrow: 1 for Stable, 2 for Variable
   * @param referralCode The 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
   * @param onBehalfOf The address of the user who will receive the debt. Should be the address of the borrower itself
   * calling the function if he wants to borrow against his own collateral, or the address of the credit delegator
   * if he has been given credit delegation allowance
   */
  function borrow(
    address asset,
    uint256 amount,
    uint256 interestRateMode,
    uint16 referralCode,
    address onBehalfOf
  ) external;

  /**
   * @notice Repays a borrowed `amount` on a specific reserve, burning the equivalent debt tokens owned
   * - E.g. User repays 100 USDC, burning 100 variable/stable debt tokens of the `onBehalfOf` address
   * @param asset The address of the borrowed underlying asset previously borrowed
   * @param amount The amount to repay
   * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
   * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
   * @param onBehalfOf The address of the user who will get his debt reduced/removed. Should be the address of the
   * user calling the function if he wants to reduce/remove his own debt, or the address of any other
   * other borrower whose debt should be removed
   * @return The final amount repaid
   */
  function repay(
    address asset,
    uint256 amount,
    uint256 interestRateMode,
    address onBehalfOf
  ) external returns (uint256);

  /**
   * @notice Repay with transfer approval of asset to be repaid done via permit function
   * see: https://eips.ethereum.org/EIPS/eip-2612 and https://eips.ethereum.org/EIPS/eip-713
   * @param asset The address of the borrowed underlying asset previously borrowed
   * @param amount The amount to repay
   * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
   * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
   * @param onBehalfOf Address of the user who will get his debt reduced/removed. Should be the address of the
   * user calling the function if he wants to reduce/remove his own debt, or the address of any other
   * other borrower whose debt should be removed
   * @param deadline The deadline timestamp that the permit is valid
   * @param permitV The V parameter of ERC712 permit sig
   * @param permitR The R parameter of ERC712 permit sig
   * @param permitS The S parameter of ERC712 permit sig
   * @return The final amount repaid
   */
  function repayWithPermit(
    address asset,
    uint256 amount,
    uint256 interestRateMode,
    address onBehalfOf,
    uint256 deadline,
    uint8 permitV,
    bytes32 permitR,
    bytes32 permitS
  ) external returns (uint256);

  /**
   * @notice Repays a borrowed `amount` on a specific reserve using the reserve aTokens, burning the
   * equivalent debt tokens
   * - E.g. User repays 100 USDC using 100 aUSDC, burning 100 variable/stable debt tokens
   * @dev  Passing uint256.max as amount will clean up any residual aToken dust balance, if the user aToken
   * balance is not enough to cover the whole debt
   * @param asset The address of the borrowed underlying asset previously borrowed
   * @param amount The amount to repay
   * - Send the value type(uint256).max in order to repay the whole debt for `asset` on the specific `debtMode`
   * @param interestRateMode The interest rate mode at of the debt the user wants to repay: 1 for Stable, 2 for Variable
   * @return The final amount repaid
   */
  function repayWithATokens(
    address asset,
    uint256 amount,
    uint256 interestRateMode
  ) external returns (uint256);

  /**
   * @notice Allows a borrower to swap his debt between stable and variable mode, or vice versa
   * @param asset The address of the underlying asset borrowed
   * @param interestRateMode The current interest rate mode of the position being swapped: 1 for Stable, 2 for Variable
   */
  function swapBorrowRateMode(address asset, uint256 interestRateMode) external;

  /**
   * @notice Rebalances the stable interest rate of a user to the current stable rate defined on the reserve.
   * - Users can be rebalanced if the following conditions are satisfied:
   *     1. Usage ratio is above 95%
   *     2. the current supply APY is below REBALANCE_UP_THRESHOLD * maxVariableBorrowRate, which means that too
   *        much has been borrowed at a stable rate and suppliers are not earning enough
   * @param asset The address of the underlying asset borrowed
   * @param user The address of the user to be rebalanced
   */
  function rebalanceStableBorrowRate(address asset, address user) external;

  /**
   * @notice Allows suppliers to enable/disable a specific supplied asset as collateral
   * @param asset The address of the underlying asset supplied
   * @param useAsCollateral True if the user wants to use the supply as collateral, false otherwise
   */
  function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;

  /**
   * @notice Function to liquidate a non-healthy position collateral-wise, with Health Factor below 1
   * - The caller (liquidator) covers `debtToCover` amount of debt of the user getting liquidated, and receives
   *   a proportionally amount of the `collateralAsset` plus a bonus to cover market risk
   * @param collateralAsset The address of the underlying asset used as collateral, to receive as result of the liquidation
   * @param debtAsset The address of the underlying borrowed asset to be repaid with the liquidation
   * @param user The address of the borrower getting liquidated
   * @param debtToCover The debt amount of borrowed `asset` the liquidator wants to cover
   * @param receiveAToken True if the liquidators wants to receive the collateral aTokens, `false` if he wants
   * to receive the underlying collateral asset directly
   */
  function liquidationCall(
    address collateralAsset,
    address debtAsset,
    address user,
    uint256 debtToCover,
    bool receiveAToken
  ) external;

  /**
   * @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
   * as long as the amount taken plus a fee is returned.
   * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
   * into consideration. For further details please visit https://docs.aave.com/developers/
   * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanReceiver interface
   * @param assets The addresses of the assets being flash-borrowed
   * @param amounts The amounts of the assets being flash-borrowed
   * @param interestRateModes Types of the debt to open if the flash loan is not returned:
   *   0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
   *   1 -> Open debt at stable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
   *   2 -> Open debt at variable rate for the value of the amount flash-borrowed to the `onBehalfOf` address
   * @param onBehalfOf The address  that will receive the debt in the case of using on `modes` 1 or 2
   * @param params Variadic packed params to pass to the receiver as extra information
   * @param referralCode The 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
   */
  function flashLoan(
    address receiverAddress,
    address[] calldata assets,
    uint256[] calldata amounts,
    uint256[] calldata interestRateModes,
    address onBehalfOf,
    bytes calldata params,
    uint16 referralCode
  ) external;

  /**
   * @notice Allows smartcontracts to access the liquidity of the pool within one transaction,
   * as long as the amount taken plus a fee is returned.
   * @dev IMPORTANT There are security concerns for developers of flashloan receiver contracts that must be kept
   * into consideration. For further details please visit https://docs.aave.com/developers/
   * @param receiverAddress The address of the contract receiving the funds, implementing IFlashLoanSimpleReceiver interface
   * @param asset The address of the asset being flash-borrowed
   * @param amount The amount of the asset being flash-borrowed
   * @param params Variadic packed params to pass to the receiver as extra information
   * @param referralCode The 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
   */
  function flashLoanSimple(
    address receiverAddress,
    address asset,
    uint256 amount,
    bytes calldata params,
    uint16 referralCode
  ) external;

  /**
   * @notice Returns the user account data across all the reserves
   * @param user The address of the user
   * @return totalCollateralBase The total collateral of the user in the base currency used by the price feed
   * @return totalDebtBase The total debt of the user in the base currency used by the price feed
   * @return availableBorrowsBase The borrowing power left of the user in the base currency used by the price feed
   * @return currentLiquidationThreshold The liquidation threshold of the user
   * @return ltv The loan to value of The user
   * @return healthFactor The current health factor of the user
   */
  function getUserAccountData(
    address user
  )
    external
    view
    returns (
      uint256 totalCollateralBase,
      uint256 totalDebtBase,
      uint256 availableBorrowsBase,
      uint256 currentLiquidationThreshold,
      uint256 ltv,
      uint256 healthFactor
    );

  /**
   * @notice Initializes a reserve, activating it, assigning an aToken and debt tokens and an
   * interest rate strategy
   * @dev Only callable by the PoolConfigurator contract
   * @param asset The address of the underlying asset of the reserve
   * @param aTokenAddress The address of the aToken that will be assigned to the reserve
   * @param stableDebtAddress The address of the StableDebtToken that will be assigned to the reserve
   * @param variableDebtAddress The address of the VariableDebtToken that will be assigned to the reserve
   * @param interestRateStrategyAddress The address of the interest rate strategy contract
   */
  function initReserve(
    address asset,
    address aTokenAddress,
    address stableDebtAddress,
    address variableDebtAddress,
    address interestRateStrategyAddress
  ) external;

  /**
   * @notice Drop a reserve
   * @dev Only callable by the PoolConfigurator contract
   * @param asset The address of the underlying asset of the reserve
   */
  function dropReserve(address asset) external;

  /**
   * @notice Updates the address of the interest rate strategy contract
   * @dev Only callable by the PoolConfigurator contract
   * @param asset The address of the underlying asset of the reserve
   * @param rateStrategyAddress The address of the interest rate strategy contract
   */
  function setReserveInterestRateStrategyAddress(
    address asset,
    address rateStrategyAddress
  ) external;

  /**
   * @notice Sets the configuration bitmap of the reserve as a whole
   * @dev Only callable by the PoolConfigurator contract
   * @param asset The address of the underlying asset of the reserve
   * @param configuration The new configuration bitmap
   */
  function setConfiguration(
    address asset,
    DataTypes.ReserveConfigurationMap calldata configuration
  ) external;

  /**
   * @notice Returns the configuration of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The configuration of the reserve
   */
  function getConfiguration(
    address asset
  ) external view returns (DataTypes.ReserveConfigurationMap memory);

  /**
   * @notice Returns the configuration of the user across all the reserves
   * @param user The user address
   * @return The configuration of the user
   */
  function getUserConfiguration(
    address user
  ) external view returns (DataTypes.UserConfigurationMap memory);

  /**
   * @notice Returns the normalized income of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The reserve's normalized income
   */
  function getReserveNormalizedIncome(address asset) external view returns (uint256);

  /**
   * @notice Returns the normalized variable debt per unit of asset
   * @dev WARNING: This function is intended to be used primarily by the protocol itself to get a
   * "dynamic" variable index based on time, current stored index and virtual rate at the current
   * moment (approx. a borrower would get if opening a position). This means that is always used in
   * combination with variable debt supply/balances.
   * If using this function externally, consider that is possible to have an increasing normalized
   * variable debt that is not equivalent to how the variable debt index would be updated in storage
   * (e.g. only updates with non-zero variable debt supply)
   * @param asset The address of the underlying asset of the reserve
   * @return The reserve normalized variable debt
   */
  function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);

  /**
   * @notice Returns the state and configuration of the reserve
   * @param asset The address of the underlying asset of the reserve
   * @return The state and configuration data of the reserve
   */
  function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);

  /**
   * @notice Validates and finalizes an aToken transfer
   * @dev Only callable by the overlying aToken of the `asset`
   * @param asset The address of the underlying asset of the aToken
   * @param from The user from which the aTokens are transferred
   * @param to The user receiving the aTokens
   * @param amount The amount being transferred/withdrawn
   * @param balanceFromBefore The aToken balance of the `from` user before the transfer
   * @param balanceToBefore The aToken balance of the `to` user before the transfer
   */
  function finalizeTransfer(
    address asset,
    address from,
    address to,
    uint256 amount,
    uint256 balanceFromBefore,
    uint256 balanceToBefore
  ) external;

  /**
   * @notice Returns the list of the underlying assets of all the initialized reserves
   * @dev It does not include dropped reserves
   * @return The addresses of the underlying assets of the initialized reserves
   */
  function getReservesList() external view returns (address[] memory);

  /**
   * @notice Returns the address of the underlying asset of a reserve by the reserve id as stored in the DataTypes.ReserveData struct
   * @param id The id of the reserve as stored in the DataTypes.ReserveData struct
   * @return The address of the reserve associated with id
   */
  function getReserveAddressById(uint16 id) external view returns (address);

  /**
   * @notice Returns the PoolAddressesProvider connected to this contract
   * @return The address of the PoolAddressesProvider
   */
  function ADDRESSES_PROVIDER() external view returns (IPoolAddressesProvider);

  /**
   * @notice Updates the protocol fee on the bridging
   * @param bridgeProtocolFee The part of the premium sent to the protocol treasury
   */
  function updateBridgeProtocolFee(uint256 bridgeProtocolFee) external;

  /**
   * @notice Updates flash loan premiums. Flash loan premium consists of two parts:
   * - A part is sent to aToken holders as extra, one time accumulated interest
   * - A part is collected by the protocol treasury
   * @dev The total premium is calculated on the total borrowed amount
   * @dev The premium to protocol is calculated on the total premium, being a percentage of `flashLoanPremiumTotal`
   * @dev Only callable by the PoolConfigurator contract
   * @param flashLoanPremiumTotal The total premium, expressed in bps
   * @param flashLoanPremiumToProtocol The part of the premium sent to the protocol treasury, expressed in bps
   */
  function updateFlashloanPremiums(
    uint128 flashLoanPremiumTotal,
    uint128 flashLoanPremiumToProtocol
  ) external;

  /**
   * @notice Configures a new category for the eMode.
   * @dev In eMode, the protocol allows very high borrowing power to borrow assets of the same category.
   * The category 0 is reserved as it's the default for volatile assets
   * @param id The id of the category
   * @param config The configuration of the category
   */
  function configureEModeCategory(uint8 id, DataTypes.EModeCategory memory config) external;

  /**
   * @notice Returns the data of an eMode category
   * @param id The id of the category
   * @return The configuration data of the category
   */
  function getEModeCategoryData(uint8 id) external view returns (DataTypes.EModeCategory memory);

  /**
   * @notice Allows a user to use the protocol in eMode
   * @param categoryId The id of the category
   */
  function setUserEMode(uint8 categoryId) external;

  /**
   * @notice Returns the eMode the user is using
   * @param user The address of the user
   * @return The eMode id
   */
  function getUserEMode(address user) external view returns (uint256);

  /**
   * @notice Resets the isolation mode total debt of the given asset to zero
   * @dev It requires the given asset has zero debt ceiling
   * @param asset The address of the underlying asset to reset the isolationModeTotalDebt
   */
  function resetIsolationModeTotalDebt(address asset) external;

  /**
   * @notice Returns the percentage of available liquidity that can be borrowed at once at stable rate
   * @return The percentage of available liquidity to borrow, expressed in bps
   */
  function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() external view returns (uint256);

  /**
   * @notice Returns the total fee on flash loans
   * @return The total fee on flashloans
   */
  function FLASHLOAN_PREMIUM_TOTAL() external view return

Tags:
ERC20, ERC165, Proxy, Swap, Liquidity, Upgradeable, Factory, Oracle|addr:0xf555ce17760be8c3c522b33ea2a8fe792375c0c3|verified:true|block:23745940|tx:0xb0207b062efc38054433c4a0755fe602633acc281af24ea238380a7cbbbeec4d|first_check:1762516725

Submitted on: 2025-11-07 12:58:46

Comments

Log in to comment.

No comments yet.