ETH Price: $2,391.36 (-9.30%)

Contract

0xC659aD8c8d98F8f0E55b3037C773A5c14221B5b5

Overview

ETH Balance

Linea Mainnet LogoLinea Mainnet LogoLinea Mainnet Logo0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

> 10 Internal Transactions found.

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
263048172025-12-03 22:01:4359 days ago1764799303
0xC659aD8c...14221B5b5
0 ETH
263048172025-12-03 22:01:4359 days ago1764799303
0xC659aD8c...14221B5b5
0 ETH
263048172025-12-03 22:01:4359 days ago1764799303
0xC659aD8c...14221B5b5
0 ETH
263048172025-12-03 22:01:4359 days ago1764799303
0xC659aD8c...14221B5b5
0 ETH
263048172025-12-03 22:01:4359 days ago1764799303
0xC659aD8c...14221B5b5
0 ETH
263048172025-12-03 22:01:4359 days ago1764799303
0xC659aD8c...14221B5b5
0 ETH
263048172025-12-03 22:01:4359 days ago1764799303
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260799092025-11-27 11:29:1465 days ago1764242954
0xC659aD8c...14221B5b5
0 ETH
260604872025-11-26 22:25:3266 days ago1764195932
0xC659aD8c...14221B5b5
0 ETH
260604872025-11-26 22:25:3266 days ago1764195932
0xC659aD8c...14221B5b5
0 ETH
260604872025-11-26 22:25:3266 days ago1764195932
0xC659aD8c...14221B5b5
0 ETH
260604872025-11-26 22:25:3266 days ago1764195932
0xC659aD8c...14221B5b5
0 ETH
260604872025-11-26 22:25:3266 days ago1764195932
0xC659aD8c...14221B5b5
0 ETH
260604872025-11-26 22:25:3266 days ago1764195932
0xC659aD8c...14221B5b5
0 ETH
View All Internal Transactions
Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MiniPoolConfigurator

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 500 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.23;

import {VersionedInitializable} from
    "../../../../contracts/protocol/libraries/upgradeability/VersionedInitializable.sol";
import {ReserveConfiguration} from
    "../../../../contracts/protocol/libraries/configuration/ReserveConfiguration.sol";
import {ILendingPool} from "../../../../contracts/interfaces/ILendingPool.sol";
import {IERC20Detailed} from
    "../../../../contracts/dependencies/openzeppelin/contracts/IERC20Detailed.sol";
import {Errors} from "../../../../contracts/protocol/libraries/helpers/Errors.sol";
import {PercentageMath} from "../../../../contracts/protocol/libraries/math/PercentageMath.sol";
import {DataTypes} from "../../../../contracts/protocol/libraries/types/DataTypes.sol";
import {IMiniPoolAddressesProvider} from
    "../../../../contracts/interfaces/IMiniPoolAddressesProvider.sol";
import {IAERC6909} from "../../../../contracts/interfaces/IAERC6909.sol";
import {IMiniPoolConfigurator} from "../../../../contracts/interfaces/IMiniPoolConfigurator.sol";
import {IMiniPool} from "../../../../contracts/interfaces/IMiniPool.sol";
import {IAddressProviderUpdatable} from
    "../../../../contracts/interfaces/IAddressProviderUpdatable.sol";

/**
 * @title MiniPoolConfigurator contract.
 * @author Conclave.
 * @notice Implements the configuration methods for the Astera MiniPool protocol.
 * @dev This contract manages reserve configurations, pool parameters, and access controls.
 */
contract MiniPoolConfigurator is
    VersionedInitializable,
    IMiniPoolConfigurator,
    IAddressProviderUpdatable
{
    using PercentageMath for uint256;
    using ReserveConfiguration for DataTypes.ReserveConfigurationMap;

    uint256 internal constant CONFIGURATOR_REVISION = 0x1;
    IMiniPoolAddressesProvider public addressesProvider;

    constructor() {
        _blockInitializing();
    }

    /**
     * @dev Only allows pool admin to call the function.
     * @param pool The address of the MiniPool being accessed.
     */
    modifier onlyPoolAdmin(address pool) {
        uint256 id = addressesProvider.getMiniPoolId(pool);
        require(addressesProvider.getPoolAdmin(id) == msg.sender, Errors.VL_CALLER_NOT_POOL_ADMIN);
        _;
    }

    /**
     * @dev Only allows main pool admin to call the function.
     */
    modifier onlyMainPoolAdmin() {
        require(addressesProvider.getMainPoolAdmin() == msg.sender, Errors.VL_CALLER_NOT_POOL_ADMIN);
        _;
    }

    /**
     * @dev Only allows emergency admin to call the function.
     */
    modifier onlyEmergencyAdmin() {
        require(
            addressesProvider.getEmergencyAdmin() == msg.sender,
            Errors.VL_CALLER_NOT_EMERGENCY_ADMIN
        );
        _;
    }

    /**
     * @dev Returns the revision number of the contract.
     * @return The revision number.
     */
    function getRevision() internal pure override returns (uint256) {
        return CONFIGURATOR_REVISION;
    }

    /**
     * @dev Initializes the MiniPoolConfigurator.
     * @param provider The address of the MiniPoolAddressesProvider.
     */
    function initialize(address provider) public initializer {
        addressesProvider = IMiniPoolAddressesProvider(provider);
    }

    /*___ Only Main Pool ___*/

    /**
     * @dev Initializes multiple reserves in a single transaction.
     * @param input Array of reserve initialization parameters.
     * @param pool The MiniPool instance to initialize reserves for.
     */
    function batchInitReserve(InitReserveInput[] calldata input, IMiniPool pool)
        external
        onlyMainPoolAdmin
    {
        for (uint256 i = 0; i < input.length; i++) {
            _initReserve(pool, input[i]);
        }
    }

    /**
     * @dev Sets the rewarder contract for a specific reserve.
     * @param asset The address of the underlying asset.
     * @param rewarder The address of the rewarder contract.
     * @param pool The MiniPool instance to set the rewarder for.
     */
    function setRewarderForReserve(address asset, address rewarder, IMiniPool pool)
        external
        onlyMainPoolAdmin
    {
        pool.setRewarderForReserve(asset, rewarder);
    }

    /**
     * @dev Updates the total flashloan premium.
     * @param newFlashloanPremiumTotal The new flashloan premium total.
     * @param pool The MiniPool instance to update.
     */
    function updateFlashloanPremiumTotal(uint128 newFlashloanPremiumTotal, IMiniPool pool)
        external
        onlyMainPoolAdmin
    {
        require(
            newFlashloanPremiumTotal <= PercentageMath.PERCENTAGE_FACTOR,
            Errors.VL_FLASHLOAN_PREMIUM_INVALID
        );
        uint128 oldFlashloanPremiumTotal = uint128(pool.FLASHLOAN_PREMIUM_TOTAL());

        pool.updateFlashLoanFee(newFlashloanPremiumTotal);
        emit FlashloanPremiumTotalUpdated(oldFlashloanPremiumTotal, newFlashloanPremiumTotal);
    }

    /**
     * @dev Sets the Astera treasury address for all mini pools.
     * @param treasury The new treasury address.
     */
    function setAsteraTreasury(address treasury) public onlyMainPoolAdmin {
        addressesProvider.setAsteraTreasury(treasury);
    }

    /**
     * @dev Sets the flow limit for an asset in a MiniPool.
     * @param asset The address of the asset.
     * @param limit The new flow limit value.
     * @param pool The MiniPool instance to update.
     */
    function setFlowLimit(address asset, uint256 limit, IMiniPool pool) public onlyMainPoolAdmin {
        pool.syncIndexesState(asset);

        addressesProvider.setFlowLimit(asset, address(pool), limit);

        pool.syncRatesState(asset);

        emit FlowLimitUpdated(asset, address(pool), limit);
    }

    /**
     * @dev Sets the interest rate strategy for a reserve.
     * @param asset The address of the underlying asset.
     * @param rateStrategyAddress The new interest rate strategy address.
     * @param pool The MiniPool instance to update.
     */
    function setReserveInterestRateStrategyAddress(
        address asset,
        address rateStrategyAddress,
        IMiniPool pool
    ) external onlyMainPoolAdmin {
        pool.syncIndexesState(asset);

        pool.setReserveInterestRateStrategyAddress(asset, rateStrategyAddress);

        pool.syncRatesState(asset);

        emit ReserveInterestRateStrategyChanged(asset, rateStrategyAddress);
    }

    /**
     * @dev Updates the Astera reserve factor for a reserve.
     * @param asset The address of the underlying asset.
     * @param reserveFactor The new reserve factor.
     * @param pool The MiniPool instance to update.
     */
    function setAsteraReserveFactor(address asset, uint256 reserveFactor, IMiniPool pool)
        external
        onlyMainPoolAdmin
    {
        pool.syncIndexesState(asset);

        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setAsteraReserveFactor(reserveFactor);

        pool.setConfiguration(asset, currentConfig.data);

        pool.syncRatesState(asset);

        emit AsteraReserveFactorChanged(asset, reserveFactor);
    }

    /**
     * @dev Sets the deposit cap for a reserve.
     * @param asset The address of the underlying asset.
     * @param depositCap The new deposit cap.
     * @param pool The MiniPool instance to update.
     */
    function setDepositCap(address asset, uint256 depositCap, IMiniPool pool)
        external
        onlyMainPoolAdmin
    {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setDepositCap(depositCap);

        pool.setConfiguration(asset, currentConfig.data);

        emit ReserveDepositCapChanged(asset, depositCap);
    }

    /**
     * @dev Internal function to initialize a single reserve.
     * @param pool The MiniPool instance.
     * @param input The reserve initialization parameters.
     */
    function _initReserve(IMiniPool pool, InitReserveInput calldata input) internal {
        address AERC6909proxy = addressesProvider.getMiniPoolToAERC6909(address(pool));
        (uint256 aTokenID, uint256 debtTokenID,) = IAERC6909(AERC6909proxy).initReserve(
            input.underlyingAsset,
            input.underlyingAssetName,
            input.underlyingAssetSymbol,
            input.underlyingAssetDecimals
        );
        pool.initReserve(
            input.underlyingAsset,
            IAERC6909(AERC6909proxy),
            aTokenID,
            debtTokenID,
            input.interestRateStrategyAddress
        );
        DataTypes.ReserveConfigurationMap memory currentConfig =
            pool.getConfiguration(input.underlyingAsset);

        currentConfig.setDecimals(input.underlyingAssetDecimals);
        currentConfig.setActive(true);
        currentConfig.setFrozen(false);
        currentConfig.setFlashLoanEnabled(true);

        pool.setConfiguration(input.underlyingAsset, currentConfig.data);

        emit ReserveInitialized(
            input.underlyingAsset, aTokenID, debtTokenID, input.interestRateStrategyAddress
        );
    }

    /*___ Only emergency admin ___*/

    /**
     * @dev Pauses or unpauses all protocol actions including aToken transfers.
     * @param val True to pause, false to unpause.
     * @param pool The MiniPool instance to update.
     */
    function setPoolPause(bool val, IMiniPool pool) external onlyEmergencyAdmin {
        pool.setPause(val);
    }

    /*___ Only pool admin ___*/

    /**
     * @dev Enables borrowing on a reserve.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to update.
     */
    function enableBorrowingOnReserve(address asset, IMiniPool pool)
        external
        onlyPoolAdmin(address(pool))
    {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setBorrowingEnabled(true);

        pool.setConfiguration(asset, currentConfig.data);

        emit BorrowingEnabledOnReserve(asset);
    }

    /**
     * @dev Disables borrowing on a reserve.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to update.
     */
    function disableBorrowingOnReserve(address asset, IMiniPool pool)
        external
        onlyPoolAdmin(address(pool))
    {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setBorrowingEnabled(false);

        pool.setConfiguration(asset, currentConfig.data);
        emit BorrowingDisabledOnReserve(asset);
    }

    /**
     * @dev Configures the collateralization parameters for a reserve.
     * @param asset The address of the underlying asset.
     * @param ltv The loan to value ratio (in basis points).
     * @param liquidationThreshold The liquidation threshold (in basis points).
     * @param liquidationBonus The liquidation bonus (in basis points).
     * @param pool The MiniPool instance to update.
     */
    function configureReserveAsCollateral(
        address asset,
        uint256 ltv,
        uint256 liquidationThreshold,
        uint256 liquidationBonus,
        IMiniPool pool
    ) external onlyPoolAdmin(address(pool)) {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        // Validation of the parameters: The LTV can
        // Only be lower or equal than the liquidation threshold
        // (Otherwise a loan against the asset would cause instantaneous liquidation).
        require(ltv <= liquidationThreshold, Errors.VL_INVALID_CONFIGURATION);

        if (liquidationThreshold != 0) {
            // Liquidation bonus must be bigger than 100.00%, otherwise the liquidator would receive less
            // Collateral than needed to cover the debt.
            require(
                liquidationBonus > PercentageMath.PERCENTAGE_FACTOR, Errors.VL_INVALID_CONFIGURATION
            );

            // If threshold * bonus is less than PERCENTAGE_FACTOR, it's guaranteed that at the moment
            // A loan is taken there is enough collateral available to cover the liquidation bonus.
            require(
                liquidationThreshold.percentMul(liquidationBonus)
                    <= PercentageMath.PERCENTAGE_FACTOR,
                Errors.VL_INVALID_CONFIGURATION
            );
        } else {
            require(liquidationBonus == 0, Errors.VL_INVALID_CONFIGURATION);
            // If the liquidation threshold is being set to 0,
            // The reserve is being disabled as collateral. To do so,
            // We need to ensure no liquidity is deposited.
            _checkNoLiquidity(asset, pool);
        }

        currentConfig.setLtv(ltv);
        currentConfig.setLiquidationThreshold(liquidationThreshold);
        currentConfig.setLiquidationBonus(liquidationBonus);

        pool.setConfiguration(asset, currentConfig.data);

        emit CollateralConfigurationChanged(asset, ltv, liquidationThreshold, liquidationBonus);
    }

    /**
     * @dev Activates a reserve.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to update.
     */
    function activateReserve(address asset, IMiniPool pool) external onlyPoolAdmin(address(pool)) {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setActive(true);

        pool.setConfiguration(asset, currentConfig.data);

        emit ReserveActivated(asset);
    }

    /**
     * @dev Deactivates a reserve.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to update.
     */
    function deactivateReserve(address asset, IMiniPool pool)
        external
        onlyPoolAdmin(address(pool))
    {
        _checkNoLiquidity(asset, pool);

        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setActive(false);

        pool.setConfiguration(asset, currentConfig.data);

        emit ReserveDeactivated(asset);
    }

    /**
     * @dev Freezes a reserve. A frozen reserve doesn't allow new deposits or borrows.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to update.
     */
    function freezeReserve(address asset, IMiniPool pool) external onlyPoolAdmin(address(pool)) {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setFrozen(true);

        pool.setConfiguration(asset, currentConfig.data);

        emit ReserveFrozen(asset);
    }

    /**
     * @dev Unfreezes a reserve.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to update.
     */
    function unfreezeReserve(address asset, IMiniPool pool) external onlyPoolAdmin(address(pool)) {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setFrozen(false);

        pool.setConfiguration(asset, currentConfig.data);

        emit ReserveUnfrozen(asset);
    }

    /**
     * @dev Enables flash loans for a reserve.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to update.
     */
    function enableFlashloan(address asset, IMiniPool pool) external onlyPoolAdmin(address(pool)) {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setFlashLoanEnabled(true);

        pool.setConfiguration(asset, currentConfig.data);

        emit EnableFlashloan(asset);
    }

    /**
     * @dev Disables flash loans for a reserve.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to update.
     */
    function disableFlashloan(address asset, IMiniPool pool)
        external
        onlyPoolAdmin(address(pool))
    {
        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setFlashLoanEnabled(false);

        pool.setConfiguration(asset, currentConfig.data);

        emit DisableFlashloan(asset);
    }

    /**
     * @dev Sets the pool admin for a MiniPool.
     * @param admin The address of the new pool admin.
     * @param pool The MiniPool instance to update.
     */
    function setPoolAdmin(address admin, IMiniPool pool) public onlyPoolAdmin(address(pool)) {
        uint256 id = addressesProvider.getMiniPoolId(address(pool));
        addressesProvider.setPoolAdmin(id, admin);
    }

    /**
     * @dev Sets the MiniPool owner treasury address.
     * @param treasury The address of the new treasury.
     * @param pool The MiniPool instance to update.
     */
    function setMinipoolOwnerTreasuryToMiniPool(address treasury, IMiniPool pool)
        public
        onlyPoolAdmin(address(pool))
    {
        uint256 id = addressesProvider.getMiniPoolId(address(pool));
        addressesProvider.setMinipoolOwnerTreasuryToMiniPool(id, treasury);
    }

    /**
     * @dev Updates the MiniPool owner reserve factor.
     * @param asset The address of the underlying asset.
     * @param reserveFactor The new reserve factor.
     * @param pool The MiniPool instance to update.
     */
    function setMinipoolOwnerReserveFactor(address asset, uint256 reserveFactor, IMiniPool pool)
        external
        onlyPoolAdmin(address(pool))
    {
        pool.syncIndexesState(asset);

        DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

        currentConfig.setMinipoolOwnerReserveFactor(reserveFactor);

        pool.setConfiguration(asset, currentConfig.data);

        pool.syncRatesState(asset);

        emit MinipoolOwnerReserveFactorChanged(asset, reserveFactor);
    }

    /**
     * @dev Sets minimal debt threshold for specific decimals
     * @param threshold Minimal debt threshold value to set.
     * @param pool MiniPool address
     */
    function setMinDebtThreshold(uint256 threshold, IMiniPool pool) external onlyMainPoolAdmin {
        pool.setMinDebtThreshold(threshold);
    }

    /**
     * @dev Checks if a reserve has zero liquidity.
     * @param asset The address of the underlying asset.
     * @param pool The MiniPool instance to check.
     */
    function _checkNoLiquidity(address asset, IMiniPool pool) internal view {
        DataTypes.MiniPoolReserveData memory reserveData = pool.getReserveData(asset);

        IAERC6909 aToken6909 = IAERC6909(reserveData.aErc6909);
        (uint256 aTokenID, uint256 debtTokenID,) = aToken6909.getIdForUnderlying(asset);

        bool hasNoShares = aToken6909.scaledTotalSupply(aTokenID) == 0
            && aToken6909.scaledTotalSupply(debtTokenID) == 0;

        require(
            hasNoShares && reserveData.currentLiquidityRate == 0, Errors.VL_RESERVE_LIQUIDITY_NOT_0
        );
    }
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.23;

/**
 * @title VersionedInitializable
 * @author Conclave, inspired by the OpenZeppelin Initializable contract
 * @notice Helper contract to implement initializer functions. To use it, replace
 * the constructor with a function that has the `initializer` modifier.
 * @dev WARNING: Unlike constructors, initializer functions must be manually
 * invoked. This applies both to deploying an Initializable contract, as well
 * as extending an Initializable contract via inheritance.
 * WARNING: When used with inheritance, manual care must be taken to not invoke
 * a parent initializer twice, or ensure that all initializers are idempotent,
 * because this is not dealt with automatically as with constructors.
 */
abstract contract VersionedInitializable {
    /**
     * @dev Indicates that the contract has been initialized through the `lastInitializedRevision` variable.
     */
    uint256 private lastInitializedRevision = 0;

    /**
     * @dev Indicates that the contract is in the process of being initialized through the `initializing` flag.
     */
    bool private initializing;

    /**
     * @dev Modifier to use in the initializer function of a contract.
     * @notice Ensures initialization can only happen once per revision.
     */
    modifier initializer() {
        uint256 revision = getRevision();
        require(
            initializing || isConstructor() || revision > lastInitializedRevision,
            "Contract instance has already been initialized"
        );

        bool isTopLevelCall = !initializing;
        if (isTopLevelCall) {
            initializing = true;
            lastInitializedRevision = revision;
        }

        _;

        if (isTopLevelCall) {
            initializing = false;
        }
    }

    /**
     * @notice Returns the revision number of the contract.
     * @dev Needs to be defined in the inherited class as a constant.
     * @return The revision number of the implementing contract.
     */
    function getRevision() internal pure virtual returns (uint256);

    /**
     * @notice Returns true if and only if the function is running in the constructor.
     * @dev Uses assembly to check if code size is zero, which is only true during construction.
     * @return True if the function is running in the constructor.
     */
    function isConstructor() private view returns (bool) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        uint256 cs;

        assembly {
            cs := extcodesize(address())
        }
        return cs == 0;
    }

    function _blockInitializing() internal {
        if (isConstructor()) {
            lastInitializedRevision = type(uint256).max;
        }
    }

    /**
     * @dev Reserved storage space to allow for layout changes in the future.
     */
    uint256[50] private ______gap;
}

File 3 of 17 : ReserveConfiguration.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.23;

import {Errors} from "../../../../contracts/protocol/libraries/helpers/Errors.sol";
import {DataTypes} from "../../../../contracts/protocol/libraries/types/DataTypes.sol";

/**
 * @title ReserveConfiguration library
 * @author Conclave
 * @notice Implements the bitmap logic to handle the reserve configuration
 */
library ReserveConfiguration {
    uint256 internal constant LTV_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000;
    uint256 internal constant LIQUIDATION_THRESHOLD_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFF;
    uint256 internal constant LIQUIDATION_BONUS_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFF;
    uint256 internal constant DECIMALS_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00FFFFFFFFFFFF;
    uint256 internal constant ACTIVE_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFF;
    uint256 internal constant FROZEN_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF;
    uint256 internal constant BORROWING_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF;
    uint256 internal constant FLASHLOAN_ENABLED_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF;
    uint256 internal constant ASTERA_RESERVE_FACTOR_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFF;
    uint256 internal constant MINIPOOL_OWNER_RESERVE_FACTOR_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFFFFF;
    uint256 internal constant DEPOSIT_CAP_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFF000000000000000000FFFFFFFFFFFFFFFFFFFFFFF;
    uint256 internal constant RESERVE_TYPE_MASK =
        0xFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    /// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed
    uint256 internal constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16;
    uint256 internal constant LIQUIDATION_BONUS_START_BIT_POSITION = 32;
    uint256 internal constant RESERVE_DECIMALS_START_BIT_POSITION = 48;
    uint256 internal constant IS_ACTIVE_START_BIT_POSITION = 56;
    uint256 internal constant IS_FROZEN_START_BIT_POSITION = 57;
    uint256 internal constant BORROWING_ENABLED_START_BIT_POSITION = 58;
    uint256 internal constant FLASHLOAN_ENABLED_START_BIT_POSITION = 59;
    uint256 internal constant ASTERA_RESERVE_FACTOR_START_BIT_POSITION = 60;
    uint256 internal constant MINIPOOL_OWNER_FACTOR_START_BIT_POSITION = 76;
    uint256 internal constant DEPOSIT_CAP_START_BIT_POSITION = 92;
    uint256 internal constant RESERVE_TYPE_START_BIT_POSITION = 164;

    uint256 internal constant MAX_VALID_LTV = type(uint16).max;
    uint256 internal constant MAX_VALID_LIQUIDATION_THRESHOLD = type(uint16).max;
    uint256 internal constant MAX_VALID_LIQUIDATION_BONUS = type(uint16).max;
    uint256 internal constant MAX_VALID_DECIMALS = type(uint8).max;
    uint256 internal constant MAX_VALID_RESERVE_FACTOR = 4000; // 40% // theorical max: type(uint16).max
    uint256 internal constant MAX_VALID_DEPOSIT_CAP = type(uint72).max; // Enough to represent SHIBA total supply.

    /**
     * @dev Sets the Loan to Value of the reserve.
     * @param self The reserve configuration map.
     * @param ltv The new loan to value value to set.
     */
    function setLtv(DataTypes.ReserveConfigurationMap memory self, uint256 ltv) internal pure {
        require(ltv <= MAX_VALID_LTV, Errors.RC_INVALID_LTV);

        self.data = (self.data & LTV_MASK) | ltv;
    }

    /**
     * @dev Gets the Loan to Value of the reserve.
     * @param self The reserve configuration map.
     * @return The current loan to value value.
     */
    function getLtv(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (uint256)
    {
        return self.data & ~LTV_MASK;
    }

    /**
     * @dev Sets the liquidation threshold of the reserve.
     * @param self The reserve configuration map.
     * @param threshold The new liquidation threshold value to set.
     */
    function setLiquidationThreshold(
        DataTypes.ReserveConfigurationMap memory self,
        uint256 threshold
    ) internal pure {
        require(threshold <= MAX_VALID_LIQUIDATION_THRESHOLD, Errors.RC_INVALID_LIQ_THRESHOLD);

        self.data = (self.data & LIQUIDATION_THRESHOLD_MASK)
            | (threshold << LIQUIDATION_THRESHOLD_START_BIT_POSITION);
    }

    /**
     * @dev Gets the liquidation threshold of the reserve.
     * @param self The reserve configuration map.
     * @return The current liquidation threshold value.
     */
    function getLiquidationThreshold(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (uint256)
    {
        return (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION;
    }

    /**
     * @dev Sets the liquidation bonus of the reserve.
     * @param self The reserve configuration map.
     * @param bonus The new liquidation bonus value to set.
     */
    function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus)
        internal
        pure
    {
        require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.RC_INVALID_LIQ_BONUS);

        self.data =
            (self.data & LIQUIDATION_BONUS_MASK) | (bonus << LIQUIDATION_BONUS_START_BIT_POSITION);
    }

    /**
     * @dev Gets the liquidation bonus of the reserve.
     * @param self The reserve configuration map.
     * @return The current liquidation bonus value.
     */
    function getLiquidationBonus(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (uint256)
    {
        return (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION;
    }

    /**
     * @dev Sets the decimals of the underlying asset of the reserve.
     * @param self The reserve configuration map.
     * @param decimals The number of decimals to set.
     */
    function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals)
        internal
        pure
    {
        require(decimals <= MAX_VALID_DECIMALS, Errors.RC_INVALID_DECIMALS);

        self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION);
    }

    /**
     * @dev Gets the decimals of the underlying asset of the reserve.
     * @param self The reserve configuration map.
     * @return The number of decimals of the asset.
     */
    function getDecimals(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (uint256)
    {
        return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION;
    }

    /**
     * @dev Sets the active state of the reserve.
     * @param self The reserve configuration map.
     * @param active The active state to set.
     */
    function setActive(DataTypes.ReserveConfigurationMap memory self, bool active) internal pure {
        self.data =
            (self.data & ACTIVE_MASK) | (uint256(active ? 1 : 0) << IS_ACTIVE_START_BIT_POSITION);
    }

    /**
     * @dev Gets the active state of the reserve.
     * @param self The reserve configuration map.
     * @return The current active state.
     */
    function getActive(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (bool)
    {
        return (self.data & ~ACTIVE_MASK) != 0;
    }

    /**
     * @dev Sets the frozen state of the reserve.
     * @param self The reserve configuration map.
     * @param frozen The frozen state to set.
     */
    function setFrozen(DataTypes.ReserveConfigurationMap memory self, bool frozen) internal pure {
        self.data =
            (self.data & FROZEN_MASK) | (uint256(frozen ? 1 : 0) << IS_FROZEN_START_BIT_POSITION);
    }

    /**
     * @dev Gets the frozen state of the reserve.
     * @param self The reserve configuration map.
     * @return The current frozen state.
     */
    function getFrozen(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (bool)
    {
        return (self.data & ~FROZEN_MASK) != 0;
    }

    /**
     * @dev Enables or disables borrowing on the reserve.
     * @param self The reserve configuration map.
     * @param enabled True if borrowing should be enabled, false otherwise.
     */
    function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled)
        internal
        pure
    {
        self.data = (self.data & BORROWING_MASK)
            | (uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION);
    }

    /**
     * @dev Gets the borrowing state of the reserve.
     * @param self The reserve configuration map.
     * @return The current borrowing state.
     */
    function getBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (bool)
    {
        return (self.data & ~BORROWING_MASK) != 0;
    }

    /**
     * @dev Sets the Astera reserve factor of the reserve.
     * @param self The reserve configuration map.
     * @param reserveFactor The reserve factor value to set.
     */
    function setAsteraReserveFactor(
        DataTypes.ReserveConfigurationMap memory self,
        uint256 reserveFactor
    ) internal pure {
        require(reserveFactor <= MAX_VALID_RESERVE_FACTOR, Errors.RC_INVALID_RESERVE_FACTOR);

        self.data = (self.data & ASTERA_RESERVE_FACTOR_MASK)
            | (reserveFactor << ASTERA_RESERVE_FACTOR_START_BIT_POSITION);
    }

    /**
     * @dev Gets the Astera reserve factor of the reserve.
     * @param self The reserve configuration map.
     * @return The current Astera reserve factor value.
     */
    function getAsteraReserveFactor(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (uint256)
    {
        return (self.data & ~ASTERA_RESERVE_FACTOR_MASK) >> ASTERA_RESERVE_FACTOR_START_BIT_POSITION;
    }

    /**
     * @notice Gets the Astera reserve factor from reserve configuration.
     * @dev This is a redefined version of getAsteraReserveFactor() for memory usage.
     * @param self The reserve configuration.
     * @return The Astera reserve factor.
     */
    function getAsteraReserveFactorMemory(DataTypes.ReserveConfigurationMap memory self)
        internal
        pure
        returns (uint256)
    {
        return (self.data & ~ASTERA_RESERVE_FACTOR_MASK) >> ASTERA_RESERVE_FACTOR_START_BIT_POSITION;
    }

    /**
     * @dev Sets the minipool owner reserve factor of the reserve.
     * @param self The reserve configuration map.
     * @param reserveFactor The reserve factor value to set.
     */
    function setMinipoolOwnerReserveFactor(
        DataTypes.ReserveConfigurationMap memory self,
        uint256 reserveFactor
    ) internal pure {
        require(reserveFactor <= MAX_VALID_RESERVE_FACTOR, Errors.RC_INVALID_RESERVE_FACTOR);

        self.data = (self.data & MINIPOOL_OWNER_RESERVE_FACTOR_MASK)
            | (reserveFactor << MINIPOOL_OWNER_FACTOR_START_BIT_POSITION);
    }

    /**
     * @dev Gets the minipool owner reserve factor of the reserve.
     * @param self The reserve configuration map.
     * @return The current minipool owner reserve factor value.
     */
    function getMinipoolOwnerReserveFactor(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (uint256)
    {
        return (self.data & ~MINIPOOL_OWNER_RESERVE_FACTOR_MASK)
            >> MINIPOOL_OWNER_FACTOR_START_BIT_POSITION;
    }

    /**
     * @notice Gets the minipool owner reserve factor from reserve configuration.
     * @param self The reserve configuration.
     * @return The minipool owner reserve factor.
     */
    function getMinipoolOwnerReserveMemory(DataTypes.ReserveConfigurationMap memory self)
        internal
        pure
        returns (uint256)
    {
        return (self.data & ~MINIPOOL_OWNER_RESERVE_FACTOR_MASK)
            >> MINIPOOL_OWNER_FACTOR_START_BIT_POSITION;
    }

    /**
     * @dev Sets the deposit cap for the reserve.
     * @param self The reserve configuration map.
     * @param depositCap The deposit cap value to set.
     */
    function setDepositCap(DataTypes.ReserveConfigurationMap memory self, uint256 depositCap)
        internal
        pure
    {
        require(depositCap <= MAX_VALID_DEPOSIT_CAP, Errors.RC_INVALID_DEPOSIT_CAP);

        self.data = (self.data & DEPOSIT_CAP_MASK) | (depositCap << DEPOSIT_CAP_START_BIT_POSITION);
    }

    /**
     * @dev Gets the deposit cap of the reserve.
     * @param self The reserve configuration map.
     * @return The current deposit cap value.
     */
    function getDepositCap(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (uint256)
    {
        return (self.data & ~DEPOSIT_CAP_MASK) >> DEPOSIT_CAP_START_BIT_POSITION;
    }

    /**
     * @dev Sets the reserve type flag.
     * @param self The reserve configuration map.
     * @param reserveType The reserve type boolean to set.
     */
    function setReserveType(DataTypes.ReserveConfigurationMap memory self, bool reserveType)
        internal
        pure
    {
        self.data = (self.data & RESERVE_TYPE_MASK)
            | (uint256(reserveType ? 1 : 0) << RESERVE_TYPE_START_BIT_POSITION);
    }

    /**
     * @dev Gets the reserve type flag.
     * @param self The reserve configuration map.
     * @return The current reserve type state.
     */
    function getReserveType(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (bool)
    {
        return (self.data & ~RESERVE_TYPE_MASK) != 0;
    }

    /**
     * @dev Gets the configuration flags of the reserve.
     * @param self The reserve configuration map.
     * @return A tuple containing the active state, frozen state, and borrowing enabled flags.
     */
    function getFlags(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (bool, bool, bool)
    {
        uint256 dataLocal = self.data;

        return (
            (dataLocal & ~ACTIVE_MASK) != 0,
            (dataLocal & ~FROZEN_MASK) != 0,
            (dataLocal & ~BORROWING_MASK) != 0
        );
    }

    /**
     * @dev Gets the configuration parameters of the reserve.
     * @param self The reserve configuration map.
     * @return A tuple containing LTV, liquidation threshold, liquidation bonus, decimals, and Astera reserve factor.
     */
    function getParams(DataTypes.ReserveConfigurationMap storage self)
        internal
        view
        returns (uint256, uint256, uint256, uint256, uint256)
    {
        uint256 dataLocal = self.data;

        return (
            dataLocal & ~LTV_MASK,
            (dataLocal & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION,
            (dataLocal & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION,
            (dataLocal & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION,
            (dataLocal & ~ASTERA_RESERVE_FACTOR_MASK) >> ASTERA_RESERVE_FACTOR_START_BIT_POSITION
        );
    }

    /**
     * @dev Gets the configuration parameters of the reserve from a memory object.
     * @param self The reserve configuration map.
     * @return A tuple containing LTV, liquidation threshold, liquidation bonus, decimals, Astera reserve factor, minipool owner reserve factor, and deposit cap.
     */
    function getParamsMemory(DataTypes.ReserveConfigurationMap memory self)
        internal
        pure
        returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256)
    {
        return (
            self.data & ~LTV_MASK,
            (self.data & ~LIQUIDATION_THRESHOLD_MASK) >> LIQUIDATION_THRESHOLD_START_BIT_POSITION,
            (self.data & ~LIQUIDATION_BONUS_MASK) >> LIQUIDATION_BONUS_START_BIT_POSITION,
            (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION,
            (self.data & ~ASTERA_RESERVE_FACTOR_MASK) >> ASTERA_RESERVE_FACTOR_START_BIT_POSITION,
            (self.data & ~MINIPOOL_OWNER_RESERVE_FACTOR_MASK)
                >> MINIPOOL_OWNER_FACTOR_START_BIT_POSITION,
            (self.data & ~DEPOSIT_CAP_MASK) >> DEPOSIT_CAP_START_BIT_POSITION
        );
    }

    /**
     * @dev Gets the configuration flags of the reserve from a memory object.
     * @param self The reserve configuration map.
     * @return A tuple containing the active state, frozen state, borrowing enabled, and flashloan enabled flags.
     */
    function getFlagsMemory(DataTypes.ReserveConfigurationMap memory self)
        internal
        pure
        returns (bool, bool, bool, bool)
    {
        return (
            (self.data & ~ACTIVE_MASK) != 0,
            (self.data & ~FROZEN_MASK) != 0,
            (self.data & ~BORROWING_MASK) != 0,
            (self.data & ~FLASHLOAN_ENABLED_MASK) != 0
        );
    }

    /**
     * @dev Sets the flashloanable flag for the reserve.
     * @param self The reserve configuration map.
     * @param flashLoanEnabled True if flashloans should be enabled, false otherwise.
     */
    function setFlashLoanEnabled(
        DataTypes.ReserveConfigurationMap memory self,
        bool flashLoanEnabled
    ) internal pure {
        self.data = (self.data & FLASHLOAN_ENABLED_MASK)
            | (uint256(flashLoanEnabled ? 1 : 0) << FLASHLOAN_ENABLED_START_BIT_POSITION);
    }

    /**
     * @dev Gets the flashloanable flag for the reserve.
     * @param self The reserve configuration map.
     * @return The current flashloan enabled state.
     */
    function getFlashLoanEnabled(DataTypes.ReserveConfigurationMap memory self)
        internal
        pure
        returns (bool)
    {
        return (self.data & ~FLASHLOAN_ENABLED_MASK) != 0;
    }
}

File 4 of 17 : ILendingPool.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

import {ILendingPoolAddressesProvider} from
    "../../contracts/interfaces/ILendingPoolAddressesProvider.sol";
import {DataTypes} from "../../contracts/protocol/libraries/types/DataTypes.sol";

/**
 * @title ILendingPool interface.
 * @author Conclave
 */
interface ILendingPool {
    /**
     * @dev Emitted on deposit()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The address initiating the deposit
     * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
     * @param amount The amount deposited
     */
    event Deposit(
        address indexed reserve, address user, address indexed onBehalfOf, uint256 amount
    );

    /**
     * @dev Emitted on withdraw()
     * @param reserve The address of the underlyng asset being withdrawn
     * @param user The address initiating the withdrawal, owner of aTokens
     * @param to 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 borrowRate The numeric rate at which the user has borrowed
     */
    event Borrow(
        address indexed reserve,
        address user,
        address indexed onBehalfOf,
        uint256 amount,
        uint256 borrowRate
    );

    /**
     * @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
     */
    event Repay(
        address indexed reserve, address indexed user, address indexed repayer, uint256 amount
    );

    /**
     * @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 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 interestRateMode The interest rate mode selected for the flash loan:
     *   0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
     *   != 0 -> Open debt at variable rate for the value of the amount flash-borrowed
     * @param amount The amount flash borrowed
     * @param premium The fee charged for the flash loan
     */
    event FlashLoan(
        address indexed target,
        address indexed initiator,
        address indexed asset,
        DataTypes.InterestRateMode interestRateMode,
        uint256 amount,
        uint256 premium
    );

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

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

    /**
     * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
     * LendingPoolCollateral manager using a DELEGATECALL
     * This allows to have the events in the generated ABI for LendingPool.
     * @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 liiquidator
     * @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. NOTE: This event is actually declared
     * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
     * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
     * gets added to the LendingPool ABI
     * @param reserve The address of the underlying asset of the reserve
     * @param liquidityRate The new liquidity rate
     * @param variableBorrowRate The new variable borrow rate
     * @param liquidityIndex The new liquidity index
     * @param variableBorrowIndex The new variable borrow index
     */
    event ReserveDataUpdated(
        address indexed reserve,
        uint256 liquidityRate,
        uint256 variableBorrowRate,
        uint256 liquidityIndex,
        uint256 variableBorrowIndex
    );

    /**
     * @dev Emitted when the flash loan fee is updated.
     * @param flashLoanPremiumTotal The new flash loan fee.
     */
    event FlashLoanFeeUpdated(uint128 flashLoanPremiumTotal);

    function deposit(address asset, bool reserveType, uint256 amount, address onBehalfOf)
        external;

    function withdraw(address asset, bool reserveType, uint256 amount, address to)
        external
        returns (uint256);

    function borrow(address asset, bool reserveType, uint256 amount, address onBehalfOf) external;

    function repay(address asset, bool reserveType, uint256 amount, address onBehalfOf)
        external
        returns (uint256);

    function miniPoolBorrow(address asset, uint256 amount, address aTokenAddress) external;

    function repayWithATokens(address asset, bool reserveType, uint256 amount)
        external
        returns (uint256);

    function setUserUseReserveAsCollateral(address asset, bool reserveType, bool useAsCollateral)
        external;

    function liquidationCall(
        address collateralAsset,
        bool collateralAssetType,
        address debtAsset,
        bool debtAssetType,
        address user,
        uint256 debtToCover,
        bool receiveAToken
    ) external;

    struct FlashLoanParams {
        address receiverAddress;
        address[] assets;
        bool[] reserveTypes;
        address onBehalfOf;
    }

    function flashLoan(
        FlashLoanParams memory flashLoanParams,
        uint256[] calldata amounts,
        uint256[] calldata modes,
        bytes calldata params
    ) external;

    function getUserAccountData(address user)
        external
        view
        returns (
            uint256 totalCollateralETH,
            uint256 totalDebtETH,
            uint256 availableBorrowsETH,
            uint256 currentLiquidationThreshold,
            uint256 ltv,
            uint256 healthFactor
        );

    function initReserve(
        address reserve,
        bool reserveType,
        address aTokenAddress,
        address variableDebtAddress,
        address interestRateStrategyAddress
    ) external;

    function setReserveInterestRateStrategyAddress(
        address reserve,
        bool reserveType,
        address rateStrategyAddress
    ) external;

    function setConfiguration(address reserve, bool reserveType, uint256 configuration) external;

    function getConfiguration(address asset, bool reserveType)
        external
        view
        returns (DataTypes.ReserveConfigurationMap memory);

    function getUserConfiguration(address user)
        external
        view
        returns (DataTypes.UserConfigurationMap memory);

    function getReserveNormalizedIncome(address asset, bool reserveType)
        external
        view
        returns (uint256);

    function getReserveNormalizedVariableDebt(address asset, bool reserveType)
        external
        view
        returns (uint256);

    function getReserveData(address asset, bool reserveType)
        external
        view
        returns (DataTypes.ReserveData memory);

    function finalizeTransfer(
        address asset,
        bool reserveType,
        address from,
        address to,
        uint256 amount,
        uint256 balanceFromBefore,
        uint256 balanceToBefore
    ) external;

    function getReservesList() external view returns (address[] memory, bool[] memory);

    function getReservesCount() external view returns (uint256);

    function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);

    function MAX_NUMBER_RESERVES() external view returns (uint256);

    function setPause(bool val) external;

    function paused() external view returns (bool);

    function setFarmingPct(address aTokenAddress, uint256 farmingPct) external;

    function setClaimingThreshold(address aTokenAddress, uint256 claimingThreshold) external;

    function setFarmingPctDrift(address aTokenAddress, uint256 farmingPctDrift) external;

    function setProfitHandler(address aTokenAddress, address profitHandler) external;

    function setVault(address aTokenAddress, address vault) external;

    function rebalance(address aTokenAddress) external;

    function getTotalManagedAssets(address aTokenAddress) external view returns (uint256);

    function updateFlashLoanFee(uint128 flashLoanPremiumTotal) external;

    function setRewarderForReserve(address asset, bool reserveType, address rewarder) external;

    function setTreasury(address asset, bool reserveType, address treasury) external;

    function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint128);

    function getATokenNonRebasingFromAtoken(address aToken) external view returns (address);

    function syncIndexesState(address asset, bool reserveType) external;

    function syncRatesState(address asset, bool reserveType) external;

    function getMinipoolFlowBorrowing(address asset) external view returns (address[] memory);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";

interface IERC20Detailed is IERC20 {
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);
}

File 6 of 17 : Errors.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.23;

/**
 * @title Errors library
 * @author Conclave
 * @notice Defines the error messages emitted by the different contracts of the Astera protocol
 * @dev Error messages prefix glossary:
 *  - VL   :: ValidationLogic
 *  - MATH :: Math libraries
 *  - AT   :: AToken/AToken6909
 *  - LP   :: Pool
 *  - RL   :: ReserveLogic
 *  - LPCM :: Liquidation
 *  - DP   :: DataProvider
 *  - O    :: Oracle
 *  - PAP  :: PoolAddressesProvider
 *  - RC   :: Reserve configuration
 *  - R    :: Rewarder
 */
library Errors {
    /// @notice Amount must be greater than 0.
    string public constant VL_INVALID_INPUT = "0";
    /// @notice Amount must be greater than 0.
    string public constant VL_INVALID_AMOUNT = "1";
    /// @notice Action requires an active reserve.
    string public constant VL_NO_ACTIVE_RESERVE = "2";
    /// @notice Action cannot be performed because the reserve is frozen.
    string public constant VL_RESERVE_FROZEN = "3";
    /// @notice User cannot withdraw more than the available balance.
    string public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = "4";
    /// @notice Transfer cannot be allowed.
    string public constant VL_TRANSFER_NOT_ALLOWED = "5";
    /// @notice Borrowing is not enabled.
    string public constant VL_BORROWING_NOT_ENABLED = "6";
    /// @notice The collateral balance is 0.
    string public constant VL_COLLATERAL_BALANCE_IS_0 = "7";
    /// @notice Health factor is lesser than the liquidation threshold.
    string public constant VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = "8";
    /// @notice There is not enough collateral to cover a new borrow.
    string public constant VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = "9";
    /// @notice Flow is not enough.
    string public constant VL_BORROW_FLOW_LIMIT_REACHED = "10";
    /// @notice Minipool position cannot be liquidated.
    string public constant VL_MINIPOOL_CANNOT_BE_LIQUIDATED = "11";
    /// @notice For repayment of stable debt, the user needs to have stable debt, otherwise, he needs to have variable debt.
    string public constant VL_NO_DEBT_OF_SELECTED_TYPE = "12";
    /// @notice To repay on behalf of a user an explicit amount to repay is needed.
    string public constant VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = "13";
    /// @notice The underlying balance needs to be greater than 0.
    string public constant VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0 = "14";
    /// @notice User deposit is already being used as collateral.
    string public constant VL_DEPOSIT_ALREADY_IN_USE = "15";
    /// @notice Inconsistent flashloan parameters.
    string public constant VL_INCONSISTENT_FLASHLOAN_PARAMS = "16";
    /// @notice Deposit cap reached.
    string public constant VL_DEPOSIT_CAP_REACHED = "17";
    /// @notice Reserve is inactive.
    string public constant VL_RESERVE_INACTIVE = "18";
    /// @notice Flashloan is disabled.
    string public constant VL_FLASHLOAN_DISABLED = "19";
    /// @notice Tranched asset cannot be flashloaned.
    string public constant VL_TRANCHED_ASSET_CANNOT_BE_FLASHLOAN = "20";
    /// @notice The caller must be the pool admin.
    string public constant VL_CALLER_NOT_POOL_ADMIN = "21";
    /// @notice U0 is greater than RAY.
    string public constant VL_U0_GREATER_THAN_RAY = "22";
    /// @notice Access restricted to lending pool.
    string public constant VL_ACCESS_RESTRICTED_TO_LENDING_POOL = "23";
    /// @notice The liquidity of the reserve needs to be 0.
    string public constant VL_RESERVE_LIQUIDITY_NOT_0 = "24";
    /// @notice Invalid risk parameters for the reserve.
    string public constant VL_INVALID_CONFIGURATION = "25";
    /// @notice The caller must be the emergency admin.
    string public constant VL_CALLER_NOT_EMERGENCY_ADMIN = "26";
    /// @notice Invalid flashloan premium.
    string public constant VL_FLASHLOAN_PREMIUM_INVALID = "27";
    /// @notice Invalid interest rate mode.
    string public constant VL_INVALID_INTEREST_RATE_MODE = "28";
    /// @notice Max reserves with flow borrowing reached.
    string public constant VL_MAX_RESERVES_WITH_FLOW_BORROWING_REACHED = "29";
    /// @notice The debt is too small to borrow and repay.
    string public constant VL_DEBT_TOO_SMALL = "30";

    /// @notice Division by zero.
    string public constant MATH_DIVISION_BY_ZERO = "31";
    /// @notice Multiplication overflow.
    string public constant MATH_MULTIPLICATION_OVERFLOW = "32";

    /// @notice Invalid amount to mint.
    string public constant AT_INVALID_MINT_AMOUNT = "33";
    /// @notice Invalid amount to burn.
    string public constant AT_INVALID_BURN_AMOUNT = "34";
    /// @notice The caller of this function must be a lending pool.
    string public constant AT_CALLER_MUST_BE_LENDING_POOL = "35";
    /// @notice Vault not initialized.
    string public constant AT_VAULT_NOT_INITIALIZED = "36";
    /// @notice Invalid address.
    string public constant AT_INVALID_ADDRESS = "37";
    /// @notice Invalid amount.
    string public constant AT_INVALID_AMOUNT = "38";
    /// @notice Invalid aToken ID.
    string public constant AT_INVALID_ATOKEN_ID = "39";
    /// @notice Invalid aToken address.
    string public constant AT_INVALID_ATOKEN_ADDRESS = "40";
    /// @notice Vault is not empty.
    string public constant AT_VAULT_NOT_EMPTY = "41";
    /// @notice Invalid controller address.
    string public constant AT_INVALID_CONTROLLER = "42";
    /// @notice Caller is not wrapper.
    string public constant AT_CALLER_NOT_WRAPPER = "43";
    /// @notice User borrows on behalf, but allowance is too small.
    string public constant AT_BORROW_ALLOWANCE_NOT_ENOUGH = "44";
    /// @notice The permit has expired.
    string public constant AT_INVALID_EXPIRATION = "45";
    /// @notice The signature is invalid.
    string public constant AT_INVALID_SIGNATURE = "46";
    /// @notice Profit handler not set.
    string public constant AT_PROFIT_HANDLER_SET = "47";
    /// @notice Caller is not AToken.
    string public constant AT_CALLER_NOT_ATOKEN = "48";
    /// @dev The aToken has already been set.
    string public constant AT_ATOKEN_ALREADY_SET = "49";
    /// @dev The debt token has already been set.
    string public constant AT_DEBT_TOKEN_ALREADY_SET = "50";
    /// @notice Caller is not the keeper.
    string public constant AT_CALLER_NOT_KEEPER = "51";
    /// @notice Reliquary allocation is more than 100%.
    string public constant AT_RELIQUARY_ALLOCATION_MORE_THAN_100 = "52";
    /// @notice The treasury has not been set.
    string public constant AT_TREASURY_NOT_SET = "53";

    /// @notice There is not enough liquidity available to borrow.
    string public constant LP_NOT_ENOUGH_LIQUIDITY_TO_BORROW = "54";
    /// @notice The caller of the function is not the lending pool configurator.
    string public constant LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = "55";
    /// @notice Caller must be an aToken.
    string public constant LP_CALLER_MUST_BE_AN_ATOKEN = "56";
    /// @notice Pool is paused.
    string public constant LP_IS_PAUSED = "57";
    /// @notice No more reserves allowed.
    string public constant LP_NO_MORE_RESERVES_ALLOWED = "58";
    /// @notice Invalid flash loan executor return.
    string public constant LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = "59";
    /// @notice Not a contract.
    string public constant LP_NOT_CONTRACT = "60";
    /// @notice Caller is not minipool.
    string public constant LP_CALLER_NOT_MINIPOOL = "61";
    /// @notice Base borrow rate can't be negative.
    string public constant LP_BASE_BORROW_RATE_CANT_BE_NEGATIVE = "62";
    /// @notice Invalid index.
    string public constant LP_INVALID_INDEX = "63";
    /// @notice Reserve has already been added.
    string public constant LP_RESERVE_ALREADY_ADDED = "64";

    /// @notice Reserve has already been initialized.
    string public constant RL_RESERVE_ALREADY_INITIALIZED = "65";
    /// @notice Reserve is not initialized.
    string public constant RL_RESERVE_NOT_INITIALIZED = "66";
    /// @notice Liquidity index overflows uint128.
    string public constant RL_LIQUIDITY_INDEX_OVERFLOW = "67";
    /// @notice Variable borrow index overflows uint128.
    string public constant RL_VARIABLE_BORROW_INDEX_OVERFLOW = "68";
    /// @notice Liquidity rate overflows uint128.
    string public constant RL_LIQUIDITY_RATE_OVERFLOW = "69";
    /// @notice Variable borrow rate overflows uint128.
    string public constant RL_VARIABLE_BORROW_RATE_OVERFLOW = "70";

    /// @notice Health factor is not below the threshold.
    string public constant LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = "71";
    /// @notice The collateral chosen cannot be liquidated.
    string public constant LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = "72";
    /// @notice User did not borrow the specified currency.
    string public constant LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER = "73";
    /// @notice There is not enough liquidity available to liquidate.
    string public constant LPCM_NOT_ENOUGH_LIQUIDITY_TO_LIQUIDATE = "74";

    /// @notice Inconsistent parameters length.
    string public constant O_INCONSISTENT_PARAMS_LENGTH = "75";
    /// @notice Price feed inconsistency.
    string public constant O_PRICE_FEED_INCONSISTENCY = "76";

    /// @notice No mini pool ID for address.
    string public constant PAP_NO_MINI_POOL_ID_FOR_ADDRESS = "77";
    /// @notice Pool ID out of range.
    string public constant PAP_POOL_ID_OUT_OF_RANGE = "78";

    /// @notice Invalid LTV.
    string public constant RC_INVALID_LTV = "79";
    /// @notice Invalid liquidation threshold.
    string public constant RC_INVALID_LIQ_THRESHOLD = "80";
    /// @notice Invalid liquidation bonus.
    string public constant RC_INVALID_LIQ_BONUS = "81";
    /// @notice Invalid decimals.
    string public constant RC_INVALID_DECIMALS = "82";
    /// @notice Invalid reserve factor.
    string public constant RC_INVALID_RESERVE_FACTOR = "83";
    /// @notice Invalid deposit cap.
    string public constant RC_INVALID_DEPOSIT_CAP = "84";
    /// @notice LendingPool not set.
    string public constant DP_LENDINGPOOL_NOT_SET = "85";
    /// @notice Reserve is not configured.
    string public constant DP_RESERVE_NOT_CONFIGURED = "86";

    /// @notice Not registered.
    string public constant R_NOT_REGISTERED = "87";
    /// @notice Too many reward tokens.
    string public constant R_TOO_MANY_REWARD_TOKENS = "88";
    /// @notice No forwarder set.
    string public constant R_NO_FORWARDER_SET = "89";
    /// @notice Claimer unauthorized.
    string public constant R_CLAIMER_UNAUTHORIZED = "90";
    /// @notice Invalid address.
    string public constant R_INVALID_ADDRESS = "91";
    /// @notice Already set.
    string public constant R_ALREADY_SET = "92";
    /// @notice Transfer error.
    string public constant R_TRANSFER_ERROR = "93";
    /// @notice Rewarder not set.
    string public constant R_REWARDER_NOT_SET = "94";
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.23;

import {Errors} from "../../../../contracts/protocol/libraries/helpers/Errors.sol";

/**
 * @title PercentageMath library
 * @author Conclave
 * @notice Provides functions to perform percentage calculations.
 * @dev Percentages are defined by default with 2 decimals of precision (100.00). The precision is indicated by `PERCENTAGE_FACTOR`.
 * @dev Operations are rounded half up.
 */
library PercentageMath {
    uint256 internal constant PERCENTAGE_FACTOR = 1e4; // Percentage plus two decimals.
    uint256 internal constant HALF_PERCENT = PERCENTAGE_FACTOR / 2;

    /**
     * @dev Executes a percentage multiplication.
     * @param value The value of which the percentage needs to be calculated.
     * @param percentage The percentage of the value to be calculated.
     * @return The percentage of `value`.
     */
    function percentMul(uint256 value, uint256 percentage) internal pure returns (uint256) {
        if (value == 0 || percentage == 0) {
            return 0;
        }

        require(
            value <= (type(uint256).max - HALF_PERCENT) / percentage,
            Errors.MATH_MULTIPLICATION_OVERFLOW
        );

        return (value * percentage + HALF_PERCENT) / PERCENTAGE_FACTOR;
    }

    /**
     * @dev Executes a percentage division.
     * @param value The value of which the percentage needs to be calculated.
     * @param percentage The percentage of the value to be calculated.
     * @return The `value` divided by the `percentage`.
     */
    function percentDiv(uint256 value, uint256 percentage) internal pure returns (uint256) {
        require(percentage != 0, Errors.MATH_DIVISION_BY_ZERO);
        uint256 halfPercentage = percentage / 2;

        require(
            value <= (type(uint256).max - halfPercentage) / PERCENTAGE_FACTOR,
            Errors.MATH_MULTIPLICATION_OVERFLOW
        );

        return (value * PERCENTAGE_FACTOR + halfPercentage) / percentage;
    }

    /**
     * @dev Executes a percentage division, rounding up.
     * @param value The value of which the percentage needs to be calculated.
     * @param percentage The percentage of the value to be calculated.
     * @return The `value` divided by the `percentage`, rounded up.
     */
    function percentDivUp(uint256 value, uint256 percentage) internal pure returns (uint256) {
        require(percentage != 0, Errors.MATH_DIVISION_BY_ZERO);

        require(
            value <= (type(uint256).max - percentage) / PERCENTAGE_FACTOR,
            Errors.MATH_MULTIPLICATION_OVERFLOW
        );

        return (value * PERCENTAGE_FACTOR + percentage) / percentage;
    }
}

File 8 of 17 : DataTypes.sol
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.23;

/**
 * @title DataTypes
 * @author Conclave
 * @notice Library containing data structures used across the protocol.
 * @dev Contains core data structures for reserves, user configurations, and system parameters.
 */
library DataTypes {
    /**
     * @notice Stores all configuration and state for a lending pool reserve.
     * @param configuration Reserve configuration parameters.
     * @param liquidityIndex Current `liquidityIndex`, expressed in ray.
     * @param variableBorrowIndex Current `variableBorrowIndex`, expressed in ray.
     * @param currentLiquidityRate Current supply interest rate, expressed in ray.
     * @param currentVariableBorrowRate Current variable borrow interest rate, expressed in ray.
     * @param lastUpdateTimestamp Timestamp of the last reserve update.
     * @param aTokenAddress Address of the `aToken` contract.
     * @param variableDebtTokenAddress Address of the variable debt token.
     * @param interestRateStrategyAddress Address of the interest rate strategy.
     * @param id Identifier of the reserve in the list of active reserves.
     */
    struct ReserveData {
        ReserveConfigurationMap configuration;
        uint128 liquidityIndex;
        uint128 variableBorrowIndex;
        uint128 currentLiquidityRate;
        uint128 currentVariableBorrowRate;
        uint40 lastUpdateTimestamp;
        address aTokenAddress;
        address variableDebtTokenAddress;
        address interestRateStrategyAddress;
        uint8 id;
    }

    /**
     * @notice Stores all configuration and state for a minipool reserve.
     * @param configuration Reserve configuration parameters.
     * @param liquidityIndex Current `liquidityIndex`, expressed in ray.
     * @param variableBorrowIndex Current `variableBorrowIndex`, expressed in ray.
     * @param currentLiquidityRate Current supply interest rate, expressed in ray.
     * @param currentVariableBorrowRate Current variable borrow interest rate, expressed in ray.
     * @param lastUpdateTimestamp Timestamp of the last reserve update.
     * @param aErc6909 Address of the ERC6909 token contract for `aTokens`.
     * @param aTokenID ID of the ERC6909 `aToken`.
     * @param variableDebtTokenID ID of the ERC6909 debt token.
     * @param interestRateStrategyAddress Address of the interest rate strategy.
     * @param id Identifier of the reserve in the list of active reserves.
     */
    struct MiniPoolReserveData {
        ReserveConfigurationMap configuration;
        uint128 liquidityIndex;
        uint128 variableBorrowIndex;
        uint128 currentLiquidityRate;
        uint128 currentVariableBorrowRate;
        uint40 lastUpdateTimestamp;
        address aErc6909;
        uint256 aTokenID;
        uint256 variableDebtTokenID;
        address interestRateStrategyAddress;
        uint8 id;
    }

    /**
     * @notice Stores the configuration parameters for a reserve.
     * @dev Encoded as a packed bitfield for gas optimization.
     *  - bits 0-15: `Loan to Value` ratio.
     *  - bits 16-31: `Liquidation threshold`.
     *  - bits 32-47: `Liquidation bonus`.
     *  - bits 48-55: Decimals of the underlying asset.
     *  - bit 56: Reserve is active.
     *  - bit 57: Reserve is frozen.
     *  - bit 58: Borrowing is enabled.
     *  - bit 59: Flashloan is enabled.
     *  - bits 60-75: `Astera` reserve factor.
     *  - bits 76-91: Minipool owner reserve factor.
     *  - bits 92-163: Deposit cap.
     *  - bit 164: Reserve type.
     *  - bits 165-255: Unused.
     */
    struct ReserveConfigurationMap {
        uint256 data;
    }

    /**
     * @notice Stores reference information for a reserve.
     * @param asset Address of the underlying asset.
     * @param reserveType Boolean indicating if the reserve is vault-boosted.
     */
    struct ReserveReference {
        address asset;
        bool reserveType;
    }

    /**
     * @notice Stores the user's configuration for all reserves.
     * @dev Encoded as a packed bitfield for gas optimization.
     */
    struct UserConfigurationMap {
        uint256 data;
    }

    /**
     * @notice Defines the possible interest rate modes for flashloans.
     * @param NONE The flashloan must not be paid back.
     * @param VARIABLE If not paid back, try to open a variable rate loan.
     */
    enum InterestRateMode {
        NONE,
        VARIABLE
    }
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

/**
 * @title IMiniPoolAddressesProvider interface.
 * @author Conclave
 */
interface IMiniPoolAddressesProvider {
    /**
     * @dev Emitted when the mini pool implementation is updated.
     * @param newAddress The address of the new MiniPool implementation.
     * @param miniPoolId The ID of the mini pool.
     */
    event MiniPoolUpdated(address indexed newAddress, uint256 indexed miniPoolId);

    /**
     * @dev Emitted when the aToken implementation is updated.
     * @param newAddress The address of the new aToken implementation.
     * @param miniPoolId The ID of the mini pool.
     */
    event ATokenUpdated(address indexed newAddress, uint256 indexed miniPoolId);

    /**
     * @dev Emitted when a flow limit is updated.
     * @param asset The asset address.
     * @param miniPool The mini pool address.
     * @param limit The new flow limit value.
     */
    event FlowLimitUpdated(address indexed asset, address indexed miniPool, uint256 indexed limit);

    /**
     * @dev Emitted when a new mini pool proxy is created.
     * @param poolId The ID of the mini pool.
     * @param id The identifier of the proxy.
     * @param newAddress The address of the created proxy contract.
     */
    event ProxyCreated(uint256 indexed poolId, bytes32 indexed id, address indexed newAddress);

    /**
     * @dev Emitted when a new proxy is created.
     * @param id The identifier of the proxy.
     * @param newAddress The address of the created proxy contract.
     */
    event ProxyCreated(bytes32 indexed id, address indexed newAddress);

    /**
     * @dev Emitted when an address is set.
     * @param id The identifier of the address.
     * @param newAddress The address being set.
     * @param hasProxy Whether the address is set in a proxy contract.
     */
    event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);

    /**
     * @dev Emitted when the mini pool configurator implementation is updated.
     * @param newAddress The address of the new MiniPoolConfigurator implementation.
     */
    event MiniPoolConfiguratorUpdated(address indexed newAddress);

    /**
     * @dev Emitted when a pool admin is set.
     * @param newAdmin The address of the new pool admin.
     * @param miniPoolId The ID of the mini pool.
     */
    event PoolAdminSet(address indexed newAdmin, uint256 indexed miniPoolId);

    /**
     * @dev Emitted when a Astera treasury is set for all mini pools.
     * @param treasury The address of the Astera treasury.
     */
    event AsteraTreasurySet(address indexed treasury);

    /**
     * @dev Emitted when a mini pool owner treasury is set.
     * @param treasury The address of the mini pool owner treasury.
     * @param miniPoolId The ID of the mini pool.
     */
    event MinipoolOwnerTreasurySet(address indexed treasury, uint256 miniPoolId);

    /**
     * @dev Emitted when the maximum number of reserves with flow borrowing is updated.
     * @param newMax The new maximum number of reserves with flow borrowing.
     */
    event MaxReservesWithFlowBorrowingUpdated(uint256 newMax);

    // Functions related to getting various addresses
    function getMiniPoolCount() external view returns (uint256);

    function getLendingPoolAddressesProvider() external view returns (address);

    function getLendingPool() external view returns (address);

    function getPoolAdmin(uint256 id) external view returns (address);

    function getMainPoolAdmin() external view returns (address);

    function getEmergencyAdmin() external view returns (address);

    function getPriceOracle() external view returns (address);

    function getFlowLimiter() external view returns (address);

    function getNumberOfReservesWithFlowBorrowing() external view returns (uint256);

    function getMaxReservesWithFlowBorrowing() external view returns (uint256);

    // Functions for MiniPool management
    function getMiniPool(uint256 id) external view returns (address);

    function getMiniPoolId(address miniPool) external view returns (uint256);

    function getMiniPoolToAERC6909(address miniPool) external view returns (address);

    function getMiniPoolToAERC6909(uint256 id) external view returns (address);

    function isMiniPool(address miniPool) external view returns (bool);

    function getMiniPoolAsteraTreasury() external view returns (address);

    function getMiniPoolOwnerTreasury(uint256 id) external view returns (address);

    function getMiniPoolConfigurator() external view returns (address);

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

    // Setters
    function setPoolAdmin(uint256 id, address newAdmin) external;

    function setFlowLimit(address asset, address miniPool, uint256 limit) external;

    function setMiniPoolImpl(address impl, uint256 miniPoolId) external;

    function setAToken6909Impl(address impl, uint256 miniPoolId) external;

    function deployMiniPool(address miniPoolImpl, address aTokenImpl, address poolAdmin)
        external
        returns (uint256);

    function setAsteraTreasury(address treasury) external;

    function setMinipoolOwnerTreasuryToMiniPool(uint256 id, address treasury) external;

    function setMiniPoolConfigurator(address configuratorImpl) external;

    function setMaxReservesWithFlowBorrowing(uint256 newMax) external;
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

import {IMiniPoolRewarder} from "../../contracts/interfaces/IMiniPoolRewarder.sol";
import {IMiniPool} from "../../contracts/interfaces/IMiniPool.sol";
import {IERC6909} from "../../contracts/interfaces/base/IERC6909.sol";

/**
 * @title IAERC6909 interface.
 * @author Conclave
 */
interface IAERC6909 is IERC6909 {
    /**
     * @dev Emitted when a new token type is initialized in the ERC6909 contract.
     * @param id The unique identifier of the token type.
     * @param name The name of the token.
     * @param symbol The symbol of the token.
     * @param decimals The number of decimals used for token amounts.
     * @param underlyingAsset The address of the underlying asset that this token represents.
     */
    event TokenInitialized(
        uint256 indexed id, string name, string symbol, uint8 decimals, address underlyingAsset
    );

    function initialize(address provider, uint256 minipoolId) external;

    function initReserve(
        address underlyingAsset,
        string memory name,
        string memory symbol,
        uint8 decimals
    ) external returns (uint256 aTokenID, uint256 debtTokenID, bool isTranche);

    function setIncentivesController(IMiniPoolRewarder controller) external;

    function transferUnderlyingTo(address to, uint256 id, uint256 amount, bool unwrap) external;

    function mintToAsteraTreasury(uint256 id, uint256 amount, uint256 index) external;

    function mintToMinipoolOwnerTreasury(uint256 id, uint256 amount, uint256 index) external;

    function mint(address user, address onBehalfOf, uint256 id, uint256 amount, uint256 index)
        external
        returns (bool);

    function burn(
        address user,
        address receiverOfUnderlying,
        uint256 id,
        uint256 amount,
        bool unwrap,
        uint256 index
    ) external;

    function approveDelegation(address delegatee, uint256 id, uint256 amount) external;

    function transferOnLiquidation(address from, address to, uint256 id, uint256 amount) external;

    function handleRepayment(address user, address onBehalfOf, uint256 id, uint256 amount)
        external
        view;

    function totalSupply(uint256 id) external view returns (uint256);

    function balanceOf(address user, uint256 id) external view returns (uint256);

    function scaledTotalSupply(uint256 id) external view returns (uint256);

    function isAToken(uint256 id) external pure returns (bool);

    function isDebtToken(uint256 id) external pure returns (bool);

    function isTranche(uint256 id) external view returns (bool);

    function getScaledUserBalanceAndSupply(address user, uint256 id)
        external
        view
        returns (uint256, uint256);

    function getNextIdForUnderlying(address underlying)
        external
        returns (uint256 aTokenID, uint256 debtTokenID, bool isTrancheRet);

    function getIdForUnderlying(address underlying)
        external
        view
        returns (uint256 aTokenID, uint256 debtTokenID, bool isTrancheRet);

    function borrowAllowance(uint256 id, address fromUser, address toUser)
        external
        view
        returns (uint256);

    function getUnderlyingAsset(uint256 id) external view returns (address);

    function getMinipoolAddress() external view returns (address);

    function getMinipoolId() external view returns (uint256);

    function getIncentivesController() external view returns (IMiniPoolRewarder);

    function ATOKEN_ADDRESSABLE_ID() external view returns (uint256);

    function DEBT_TOKEN_ADDRESSABLE_ID() external view returns (uint256);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

import {IMiniPoolAddressesProvider} from "./IMiniPoolAddressesProvider.sol";
import {IMiniPool} from "./IMiniPool.sol";

/**
 * @title IMiniPoolConfigurator interface.
 * @author Conclave
 */
interface IMiniPoolConfigurator {
    struct InitReserveInput {
        uint8 underlyingAssetDecimals;
        address interestRateStrategyAddress;
        address underlyingAsset;
        string underlyingAssetName;
        string underlyingAssetSymbol;
    }

    struct UpdateATokenInput {
        address asset;
        address treasury;
        address incentivesController;
        string name;
        string symbol;
        address implementation;
        bytes params;
    }

    struct UpdateDebtTokenInput {
        address asset;
        address incentivesController;
        string name;
        string symbol;
        address implementation;
        bytes params;
    }

    /**
     * @dev Emitted when a reserve is initialized.
     * @param asset The address of the underlying asset of the reserve
     * @param aTokenId The ID of the associated aToken in the AERC6909 contract
     * @param debtTokenID The ID of the associated debt token in the AERC6909 contract
     * @param interestRateStrategyAddress The address of the interest rate strategy for the reserve
     */
    event ReserveInitialized(
        address indexed asset,
        uint256 indexed aTokenId,
        uint256 indexed debtTokenID,
        address interestRateStrategyAddress
    );

    /**
     * @dev Emitted when borrowing is enabled on a reserve
     * @param asset The address of the underlying asset of the reserve
     */
    event BorrowingEnabledOnReserve(address indexed asset);

    /**
     * @dev Emitted when borrowing is disabled on a reserve
     * @param asset The address of the underlying asset of the reserve
     */
    event BorrowingDisabledOnReserve(address indexed asset);

    /**
     * @dev Emitted when the collateralization risk parameters for the specified asset are updated.
     * @param asset The address of the underlying asset of the reserve
     * @param ltv The loan to value of the asset when used as collateral
     * @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
     * @param liquidationBonus The bonus liquidators receive to liquidate this asset
     */
    event CollateralConfigurationChanged(
        address indexed asset, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus
    );

    /**
     * @dev Emitted when a reserve is activated
     * @param asset The address of the underlying asset of the reserve
     */
    event ReserveActivated(address indexed asset);

    /**
     * @dev Emitted when a reserve is deactivated
     * @param asset The address of the underlying asset of the reserve
     */
    event ReserveDeactivated(address indexed asset);

    /**
     * @dev Emitted when a reserve is frozen
     * @param asset The address of the underlying asset of the reserve
     */
    event ReserveFrozen(address indexed asset);

    /**
     * @dev Emitted when a reserve is unfrozen
     * @param asset The address of the underlying asset of the reserve
     */
    event ReserveUnfrozen(address indexed asset);

    /**
     * @dev Emitted when FL is enabled
     * @param asset The address of the underlying asset of the reserve
     */
    event EnableFlashloan(address indexed asset);

    /**
     * @dev Emitted when FL is disabled
     * @param asset The address of the underlying asset of the reserve
     */
    event DisableFlashloan(address indexed asset);

    /**
     * @dev Emitted when a Astera reserve factor is updated
     * @param asset The address of the underlying asset of the reserve
     * @param factor The new reserve factor
     */
    event AsteraReserveFactorChanged(address indexed asset, uint256 factor);

    /**
     * @dev Emitted when a minipool owner reserve factor is updated
     * @param asset The address of the underlying asset of the reserve
     * @param factor The new reserve factor
     */
    event MinipoolOwnerReserveFactorChanged(address indexed asset, uint256 factor);

    /**
     * @dev Emitted when the reserve deposit cap is updated
     * @param asset The address of the underlying asset of the reserve
     * @param depositCap The new depositCap, a 0 means no deposit cap
     */
    event ReserveDepositCapChanged(address indexed asset, uint256 depositCap);

    /**
     * @dev Emitted when a reserve interest strategy contract is updated
     * @param asset The address of the underlying asset of the reserve
     * @param strategy The new address of the interest strategy contract
     */
    event ReserveInterestRateStrategyChanged(address indexed asset, address strategy);

    /**
     * @dev Emitted when the flow limit for a miniPool is updated
     * @param asset The address of the underlying asset
     * @param miniPool The address of the miniPool
     * @param limit The new flow limit amount
     */
    event FlowLimitUpdated(address indexed asset, address indexed miniPool, uint256 limit);

    /**
     * @dev Emitted when the total premium on flashloans is updated.
     * @param oldFlashloanPremiumTotal The old premium, expressed in bps
     * @param newFlashloanPremiumTotal The new premium, expressed in bps
     */
    event FlashloanPremiumTotalUpdated(
        uint128 oldFlashloanPremiumTotal, uint128 newFlashloanPremiumTotal
    );

    function batchInitReserve(InitReserveInput[] calldata input, IMiniPool pool) external;

    function setRewarderForReserve(address asset, address rewarder, IMiniPool pool) external;

    function updateFlashloanPremiumTotal(uint128 newFlashloanPremiumTotal, IMiniPool pool)
        external;

    function setAsteraTreasury(address treasury) external;

    function setFlowLimit(address asset, uint256 limit, IMiniPool pool) external;

    function setReserveInterestRateStrategyAddress(
        address asset,
        address rateStrategyAddress,
        IMiniPool pool
    ) external;

    function setAsteraReserveFactor(address asset, uint256 reserveFactor, IMiniPool pool)
        external;

    function setDepositCap(address asset, uint256 depositCap, IMiniPool pool) external;

    function setPoolPause(bool val, IMiniPool pool) external;

    function enableBorrowingOnReserve(address asset, IMiniPool pool) external;

    function disableBorrowingOnReserve(address asset, IMiniPool pool) external;

    function configureReserveAsCollateral(
        address asset,
        uint256 ltv,
        uint256 liquidationThreshold,
        uint256 liquidationBonus,
        IMiniPool pool
    ) external;

    function activateReserve(address asset, IMiniPool pool) external;

    function deactivateReserve(address asset, IMiniPool pool) external;

    function freezeReserve(address asset, IMiniPool pool) external;

    function unfreezeReserve(address asset, IMiniPool pool) external;

    function enableFlashloan(address asset, IMiniPool pool) external;

    function disableFlashloan(address asset, IMiniPool pool) external;

    function setPoolAdmin(address admin, IMiniPool pool) external;

    function setMinipoolOwnerTreasuryToMiniPool(address treasury, IMiniPool pool) external;

    function setMinipoolOwnerReserveFactor(address asset, uint256 reserveFactor, IMiniPool pool)
        external;
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

import {IMiniPoolAddressesProvider} from "../../contracts/interfaces/IMiniPoolAddressesProvider.sol";
import {IAERC6909} from "../../contracts/interfaces/IAERC6909.sol";
import {DataTypes} from "../../contracts/protocol/libraries/types/DataTypes.sol";

/**
 * @title IMiniPool interface.
 * @author Conclave
 */
interface IMiniPool {
    /**
     * @dev Emitted on deposit()
     * @param reserve The address of the underlying asset of the reserve
     * @param user The address initiating the deposit
     * @param onBehalfOf The beneficiary of the deposit, receiving the aTokens
     * @param amount The amount deposited
     */
    event Deposit(
        address indexed reserve, address user, address indexed onBehalfOf, uint256 amount
    );

    /**
     * @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 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 borrowRate The numeric rate at which the user has borrowed
     */
    event Borrow(
        address indexed reserve,
        address user,
        address indexed onBehalfOf,
        uint256 amount,
        uint256 borrowRate
    );

    /**
     * @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
     */
    event Repay(
        address indexed reserve, address indexed user, address indexed repayer, uint256 amount
    );

    /**
     * @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 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 interestRateMode The interest rate mode selected for the flash loan:
     *   0 -> Don't open any debt, just revert if funds can't be transferred from the receiver
     *   != 0 -> Open debt at variable rate for the value of the amount flash-borrowed
     * @param amount The amount flash borrowed
     * @param premium The fee charged for the flash loan
     */
    event FlashLoan(
        address indexed target,
        address indexed initiator,
        address indexed asset,
        DataTypes.InterestRateMode interestRateMode,
        uint256 amount,
        uint256 premium
    );

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

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

    /**
     * @dev Emitted when a borrower is liquidated. This event is emitted by the LendingPool via
     * LendingPoolCollateral manager using a DELEGATECALL
     * This allows to have the events in the generated ABI for LendingPool.
     * @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 liiquidator
     * @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. NOTE: This event is actually declared
     * in the ReserveLogic library and emitted in the updateInterestRates() function. Since the function is internal,
     * the event will actually be fired by the LendingPool contract. The event is therefore replicated here so it
     * gets added to the LendingPool ABI
     * @param reserve The address of the underlying asset of the reserve
     * @param liquidityRate The new liquidity rate
     * @param variableBorrowRate The new variable borrow rate
     * @param liquidityIndex The new liquidity index
     * @param variableBorrowIndex The new variable borrow index
     */
    event ReserveDataUpdated(
        address indexed reserve,
        uint256 liquidityRate,
        uint256 variableBorrowRate,
        uint256 liquidityIndex,
        uint256 variableBorrowIndex
    );

    /**
     * @dev Emitted when set new minimal debt threshold
     * @param threshold - minimal debt threshold value to set
     */
    event MinDebtThresholdSet(uint256 indexed threshold);

    function deposit(address asset, bool wrap, uint256 amount, address onBehalfOf) external;

    function withdraw(address asset, bool unwrap, uint256 amount, address to)
        external
        returns (uint256);

    function borrow(address asset, bool unwrap, uint256 amount, address onBehalfOf) external;

    function repay(address asset, bool wrap, uint256 amount, address onBehalfOf)
        external
        returns (uint256);

    function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external;

    function liquidationCall(
        address collateralAsset,
        bool unwrap,
        address debtAsset,
        bool wrap,
        address user,
        uint256 debtToCover,
        bool receiveAToken
    ) external;

    function setMinDebtThreshold(uint256 threshold) external;

    struct FlashLoanParams {
        address receiverAddress;
        address[] assets;
        address onBehalfOf;
    }

    function flashLoan(
        FlashLoanParams memory flashLoanParams,
        uint256[] calldata amounts,
        uint256[] calldata modes,
        bytes calldata params
    ) external;

    function getUserAccountData(address user)
        external
        view
        returns (
            uint256 totalCollateralETH,
            uint256 totalDebtETH,
            uint256 availableBorrowsETH,
            uint256 currentLiquidationThreshold,
            uint256 ltv,
            uint256 healthFactor
        );

    function initReserve(
        address asset,
        IAERC6909 aTokenAddress,
        uint256 aTokenID,
        uint256 variableDebtTokenID,
        address interestRateStrategyAddress
    ) external;

    function setReserveInterestRateStrategyAddress(address reserve, address rateStrategyAddress)
        external;

    function setConfiguration(address reserve, uint256 configuration) external;

    function getConfiguration(address asset)
        external
        view
        returns (DataTypes.ReserveConfigurationMap memory);

    function getUserConfiguration(address user)
        external
        view
        returns (DataTypes.UserConfigurationMap memory);

    function getReserveNormalizedIncome(address asset) external view returns (uint256);

    function getReserveNormalizedVariableDebt(address asset) external view returns (uint256);

    function getReserveData(address asset)
        external
        view
        returns (DataTypes.MiniPoolReserveData memory);

    function finalizeTransfer(
        address asset,
        address from,
        address to,
        uint256 amount,
        uint256 balanceFromAfter,
        uint256 balanceToBefore
    ) external;

    function getReservesList() external view returns (address[] memory, bool[] memory);

    function getReservesCount() external view returns (uint256);

    function getAddressesProvider() external view returns (IMiniPoolAddressesProvider);

    function MAX_NUMBER_RESERVES() external view returns (uint256);

    function FLASHLOAN_PREMIUM_TOTAL() external view returns (uint256);

    function setPause(bool val) external;

    function paused() external view returns (bool);

    function setRewarderForReserve(address asset, address rewarder) external;

    function updateFlashLoanFee(uint128 flashLoanPremiumTotal) external;

    function syncIndexesState(address asset) external;

    function syncRatesState(address asset) external;

    function syncState(address asset) external;

    function minDebtThreshold(uint8 decimals) external view returns (uint256);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

/**
 * @title IAddressProviderUpdatable interface.
 * @author Conclave
 */
interface IAddressProviderUpdatable {
    /**
     * @dev Updates the implementation of a mini pool.
     * @param addressProvider The new implementation address.
     */
    function initialize(address addressProvider) external;
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

/**
 * @title LendingPoolAddressesProvider interface.
 * @author Conclave
 */
interface ILendingPoolAddressesProvider {
    /**
     * @dev Emitted when the market identifier is updated.
     * @param newMarketId The new market identifier for the protocol.
     */
    event MarketIdSet(string newMarketId);

    /**
     * @dev Emitted when the lending pool implementation is updated.
     * @param newAddress The address of the new `LendingPool` implementation contract.
     */
    event LendingPoolUpdated(address indexed newAddress);

    /**
     * @dev Emitted when the configuration admin is updated.
     * @param newAddress The address of the new configuration admin that can modify pool parameters.
     */
    event ConfigurationAdminUpdated(address indexed newAddress);

    /**
     * @dev Emitted when the emergency admin is updated.
     * @param newAddress The address of the new emergency admin that can pause protocol functions.
     */
    event EmergencyAdminUpdated(address indexed newAddress);

    /**
     * @dev Emitted when the lending pool configurator implementation is updated.
     * @param newAddress The address of the new `LendingPoolConfigurator` implementation contract.
     */
    event LendingPoolConfiguratorUpdated(address indexed newAddress);

    /**
     * @dev Emitted when the price oracle is updated.
     * @param newAddress The address of the new `PriceOracle` contract used for asset price feeds.
     */
    event PriceOracleUpdated(address indexed newAddress);

    /**
     * @dev Emitted when a new proxy contract is created.
     * @param id The identifier `bytes32` of the proxy being created.
     * @param newAddress The address of the newly created proxy contract.
     */
    event ProxyCreated(bytes32 indexed id, address indexed newAddress);

    /**
     * @dev Emitted when an address mapping is set in the provider.
     * @param id The identifier `bytes32` for the address being set.
     * @param newAddress The new address being mapped to the identifier.
     * @param hasProxy Boolean indicating if the address is set behind a proxy contract.
     */
    event AddressSet(bytes32 id, address indexed newAddress, bool hasProxy);

    /**
     * @dev Emitted when the MiniPool addresses provider is updated.
     * @param newAddress The new MiniPool addresses provider address.
     */
    event MiniPoolAddressesProviderUpdated(address indexed newAddress);

    /**
     * @dev Emitted when the flow limiter is updated.
     * @param newAddress The new flow limiter address.
     */
    event FlowLimiterUpdated(address indexed newAddress);

    function getMiniPoolAddressesProvider() external view returns (address);

    function getLendingPool() external view returns (address);

    function getLendingPoolConfigurator() external view returns (address);

    function getPoolAdmin() external view returns (address);

    function getEmergencyAdmin() external view returns (address);

    function getPriceOracle() external view returns (address);

    function getFlowLimiter() external view returns (address);

    function getAddress(bytes32 id) external view returns (address);

    function setAddress(bytes32 id, address newAddress) external;

    function setAddressAsProxy(bytes32 id, address impl) external;

    function setLendingPoolImpl(address pool) external;

    function setLendingPoolConfiguratorImpl(address configurator) external;

    function setPoolAdmin(address admin) external;

    function setEmergencyAdmin(address admin) external;

    function setPriceOracle(address priceOracle) external;

    function setMiniPoolAddressesProvider(address provider) external;

    function setFlowLimiter(address flowLimiter) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

/**
 * @title IMiniPoolRewarder interface.
 * @author Conclave
 */
interface IMiniPoolRewarder {
    /**
     * @dev Emitted when rewards are accrued for a user
     * @param user The address of the user for whom rewards are being accrued
     * @param amount The amount of rewards accrued
     */
    event RewardsAccrued(address indexed user, uint256 amount);

    /**
     * @dev Emitted when rewards are claimed by a user
     * @param user The address of the user who is claiming rewards
     * @param to The address that will receive the claimed rewards
     * @param amount The amount of rewards claimed
     */
    event RewardsClaimed(address indexed user, address indexed to, uint256 amount);

    /**
     * @dev Emitted when rewards are claimed on behalf of a user
     * @param user The address of the user for whom rewards are being claimed
     * @param to The address that will receive the claimed rewards
     * @param claimer The address that initiated the claim
     * @param amount The amount of rewards claimed
     */
    event RewardsClaimed(
        address indexed user, address indexed to, address indexed claimer, uint256 amount
    );

    /**
     * @dev Emitted when a claimer is set for a user
     * @param user The address of the user
     * @param claimer The address authorized to claim rewards on behalf of the user
     */
    event ClaimerSet(address indexed user, address indexed claimer);

    function getAssetData(address asset) external view returns (uint256, uint256, uint256);

    function assets(address asset) external view returns (uint128, uint128, uint256);

    function setClaimer(address user, address claimer) external;

    function getClaimer(address user) external view returns (address);

    function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond)
        external;

    function handleAction(uint256 assetID, address user, uint256 userBalance, uint256 totalSupply)
        external;

    function getRewardsBalance(address[] calldata assets, address user)
        external
        view
        returns (uint256);

    function claimRewards(address[] calldata assets, uint256 amount, address to)
        external
        returns (uint256);

    function claimRewardsOnBehalf(
        address[] calldata assets,
        uint256 amount,
        address user,
        address to
    ) external returns (uint256);

    function getUserUnclaimedRewards(address user) external view returns (uint256);

    function getUserAssetData(address user, address asset) external view returns (uint256);

    function REWARD_TOKEN() external view returns (address);

    function PRECISION() external view returns (uint8);

    function DISTRIBUTION_END() external view returns (uint256);
}

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.8.0;

/**
 * @title IERC6909 interface.
 * @author Conclave
 */
interface IERC6909 {
    /**
     * @dev Emitted when tokens are transferred from one account to another
     * @param by The address that initiated the transfer
     * @param from The address tokens are transferred from
     * @param to The address tokens are transferred to
     * @param id The token identifier
     * @param amount The amount of tokens transferred
     */
    event Transfer(
        address by, address indexed from, address indexed to, uint256 indexed id, uint256 amount
    );

    /**
     * @dev Emitted when an operator is set or unset for an owner
     * @param owner The address of the token owner
     * @param operator The address being granted or revoked operator status
     * @param approved True if the operator is approved, false to revoke approval
     */
    event OperatorSet(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Emitted when an approval is set for a specific token
     * @param owner The address of the token owner
     * @param spender The address of the spender being approved
     * @param id The token identifier
     * @param amount The amount of tokens approved
     */
    event Approval(
        address indexed owner, address indexed spender, uint256 indexed id, uint256 amount
    );

    function name(uint256 id) external view returns (string memory);

    function symbol(uint256 id) external view returns (string memory);

    function decimals(uint256 id) external view returns (uint8);

    function tokenURI(uint256 id) external view returns (string memory);

    function balanceOf(address owner, uint256 id) external view returns (uint256 amount);

    function allowance(address owner, address spender, uint256 id)
        external
        view
        returns (uint256 amount);

    function isOperator(address owner, address spender) external view returns (bool status);

    function transfer(address to, uint256 id, uint256 amount) external returns (bool);

    function transferFrom(address from, address to, uint256 id, uint256 amount)
        external
        returns (bool);

    function approve(address spender, uint256 id, uint256 amount) external returns (bool);

    function setOperator(address operator, bool approved) external returns (bool);

    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "eth-gas-reporter/=node_modules/eth-gas-reporter/",
    "forge-std/=lib/forge-std/src/",
    "hardhat/=node_modules/hardhat/",
    "pythnetwork/pyth-sdk-solidity/=node_modules/@pythnetwork/pyth-sdk-solidity/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "solady/=lib/solady/src/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@pythnetwork/=node_modules/@pythnetwork/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 500
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"factor","type":"uint256"}],"name":"AsteraReserveFactorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"BorrowingDisabledOnReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"BorrowingEnabledOnReserve","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"ltv","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationThreshold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liquidationBonus","type":"uint256"}],"name":"CollateralConfigurationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"DisableFlashloan","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"EnableFlashloan","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"oldFlashloanPremiumTotal","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"newFlashloanPremiumTotal","type":"uint128"}],"name":"FlashloanPremiumTotalUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"miniPool","type":"address"},{"indexed":false,"internalType":"uint256","name":"limit","type":"uint256"}],"name":"FlowLimitUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"factor","type":"uint256"}],"name":"MinipoolOwnerReserveFactorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"ReserveActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"ReserveDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"depositCap","type":"uint256"}],"name":"ReserveDepositCapChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"ReserveFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"uint256","name":"aTokenId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"debtTokenID","type":"uint256"},{"indexed":false,"internalType":"address","name":"interestRateStrategyAddress","type":"address"}],"name":"ReserveInitialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"address","name":"strategy","type":"address"}],"name":"ReserveInterestRateStrategyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"}],"name":"ReserveUnfrozen","type":"event"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"activateReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addressesProvider","outputs":[{"internalType":"contract IMiniPoolAddressesProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"underlyingAssetDecimals","type":"uint8"},{"internalType":"address","name":"interestRateStrategyAddress","type":"address"},{"internalType":"address","name":"underlyingAsset","type":"address"},{"internalType":"string","name":"underlyingAssetName","type":"string"},{"internalType":"string","name":"underlyingAssetSymbol","type":"string"}],"internalType":"struct IMiniPoolConfigurator.InitReserveInput[]","name":"input","type":"tuple[]"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"batchInitReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"ltv","type":"uint256"},{"internalType":"uint256","name":"liquidationThreshold","type":"uint256"},{"internalType":"uint256","name":"liquidationBonus","type":"uint256"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"configureReserveAsCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"deactivateReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"disableBorrowingOnReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"disableFlashloan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"enableBorrowingOnReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"enableFlashloan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"freezeReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"provider","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"reserveFactor","type":"uint256"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setAsteraReserveFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"treasury","type":"address"}],"name":"setAsteraTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"depositCap","type":"uint256"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setDepositCap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"limit","type":"uint256"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setFlowLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setMinDebtThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"reserveFactor","type":"uint256"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setMinipoolOwnerReserveFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"treasury","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setMinipoolOwnerTreasuryToMiniPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setPoolAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"val","type":"bool"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setPoolPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"rateStrategyAddress","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setReserveInterestRateStrategyAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"rewarder","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"setRewarderForReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"unfreezeReserve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"newFlashloanPremiumTotal","type":"uint128"},{"internalType":"contract IMiniPool","name":"pool","type":"address"}],"name":"updateFlashloanPremiumTotal","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052600080553480156200001557600080fd5b506200002062000026565b62000036565b303b62000034576000196000555b565b61409e80620000466000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c806391d77d71116100e3578063d006bc171161008c578063eb2f6b1f11610066578063eb2f6b1f1461034a578063fa3f8ff41461035d578063fe3d98431461037057600080fd5b8063d006bc1714610311578063d1680b6c14610324578063e65040bc1461033757600080fd5b8063c4d66de8116100bd578063c4d66de8146102bc578063c72c4d10146102cf578063c7864387146102fe57600080fd5b806391d77d71146102835780639892f75914610296578063bf81672f146102a957600080fd5b8063517f63dc11610145578063787203881161011f578063787203881461024a5780637a993c991461025d5780638b9cea7c1461027057600080fd5b8063517f63dc1461021157806370c3eb3114610224578063773a66571461023757600080fd5b806346f39cf31161017657806346f39cf3146101d85780634782a367146101eb57806348fca5a6146101fe57600080fd5b806318ce73e71461019d57806318e13279146101b257806325d2ca51146101c5575b600080fd5b6101b06101ab366004613a39565b610383565b005b6101b06101c0366004613a39565b6105d0565b6101b06101d3366004613a72565b610814565b6101b06101e6366004613af8565b61090b565b6101b06101f9366004613a39565b610b9a565b6101b061020c366004613b2f565b610dde565b6101b061021f366004613a39565b610fed565b6101b0610232366004613b84565b611231565b6101b0610245366004613af8565b61143a565b6101b0610258366004613a39565b611742565b6101b061026b366004613ba2565b611949565b6101b061027e366004613bc6565b611a5c565b6101b0610291366004613a39565b611ddf565b6101b06102a4366004613af8565b612023565b6101b06102b7366004613a39565b61224a565b6101b06102ca366004613ba2565b61248e565b6034546102e2906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6101b061030c366004613a39565b61257a565b6101b061031f366004613a39565b6127c8565b6101b0610332366004613b2f565b612a0c565b6101b0610345366004613c2a565b612b25565b6101b0610358366004613af8565b612c36565b6101b061036b366004613c48565b612e02565b6101b061037e366004613a39565b612ee0565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa1580156103d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f59190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015610443573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104679190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906104b35760405162461bcd60e51b81526004016104aa9190613cb3565b60405180910390fd5b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa1580156104fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105229190613d8a565b905061052f8160006130b2565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b15801561057d57600080fd5b505af1158015610591573d6000803e3d6000fd5b50506040516001600160a01b03881692507fe9a7e5fd4fc8ea18e602350324bf48e8f05d12434af0ce0be05743e6a5fdcb9e9150600090a25050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa15801561061e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106429190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015610690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b49190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906106f75760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107669190613d8a565b90506107738160016130e0565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b1580156107c157600080fd5b505af11580156107d5573d6000803e3d6000fd5b50506040516001600160a01b03881692507f85dc710add8a0914461a7dc5a63f6fc529a7700f8c6089a3faf5e93256ccf12a9150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa15801561085d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108819190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906108c45760405162461bcd60e51b81526004016104aa9190613cb3565b5060005b82811015610905576108fd828585848181106108e6576108e6613da6565b90506020028101906108f89190613dbc565b61310e565b6001016108c8565b50505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015610954573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109789190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906109bb5760405162461bcd60e51b81526004016104aa9190613cb3565b50604051635595a8fb60e11b81526001600160a01b03848116600483015282169063ab2b51f690602401600060405180830381600087803b1580156109ff57600080fd5b505af1158015610a13573d6000803e3d6000fd5b505060405163c44b11f760e01b81526001600160a01b038681166004830152600093508416915063c44b11f790602401602060405180830381865afa158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a849190613d8a565b9050610a908184613492565b8051604051635c69493b60e11b81526001600160a01b03868116600483015260248201929092529083169063b8d2927690604401600060405180830381600087803b158015610ade57600080fd5b505af1158015610af2573d6000803e3d6000fd5b5050604051634c63ed2760e11b81526001600160a01b038781166004830152851692506398c7da4e9150602401600060405180830381600087803b158015610b3957600080fd5b505af1158015610b4d573d6000803e3d6000fd5b50505050836001600160a01b03167fee3084d98b631d079c0b340ac21f6851def11a0ef269af72ad049756e5de874084604051610b8c91815260200190565b60405180910390a250505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015610be8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0c9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015610c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090610cc15760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa158015610d0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d309190613d8a565b9050610d3d8160006130e0565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b158015610d8b57600080fd5b505af1158015610d9f573d6000803e3d6000fd5b50506040516001600160a01b03881692507f838ecdc4709a31a26db48b0c853212cedde3f725f07030079d793fb0719647609150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015610e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4b9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090610e8e5760405162461bcd60e51b81526004016104aa9190613cb3565b50604051635595a8fb60e11b81526001600160a01b03848116600483015282169063ab2b51f690602401600060405180830381600087803b158015610ed257600080fd5b505af1158015610ee6573d6000803e3d6000fd5b5050604051631d2118f960e01b81526001600160a01b038681166004830152858116602483015284169250631d2118f99150604401600060405180830381600087803b158015610f3557600080fd5b505af1158015610f49573d6000803e3d6000fd5b5050604051634c63ed2760e11b81526001600160a01b038681166004830152841692506398c7da4e9150602401600060405180830381600087803b158015610f9057600080fd5b505af1158015610fa4573d6000803e3d6000fd5b50506040516001600160a01b038581168252861692507f5644b64ebb0ce18c4032248ca52f58355469092ff072866c3dcd8640e817d6a5915060200160405180910390a2505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa15801561103b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105f9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa1580156110ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d19190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906111145760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa15801561115f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111839190613d8a565b90506111908160016134e9565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b1580156111de57600080fd5b505af11580156111f2573d6000803e3d6000fd5b50506040516001600160a01b03881692507f42924e374f01dd5c0b51fa6ab454551ccf573844ad021001faec9b97efa22db69150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa15801561127a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906112e15760405162461bcd60e51b81526004016104aa9190613cb3565b50604080518082019091526002815261323760f01b60208201526127106001600160801b03841611156113275760405162461bcd60e51b81526004016104aa9190613cb3565b506000816001600160a01b031663074b2e436040518163ffffffff1660e01b8152600401602060405180830381865afa158015611368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138c9190613c6d565b604051636bb040f160e11b81526001600160801b03851660048201529091506001600160a01b0383169063d76081e290602401600060405180830381600087803b1580156113d957600080fd5b505af11580156113ed573d6000803e3d6000fd5b5050604080516001600160801b038086168252871660208201527f71aba182c9d0529b516de7a78bed74d49c207ef7e152f52f7ea5d8730138f643935001905060405180910390a1505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015611488573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ac9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa1580156114fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906115615760405162461bcd60e51b81526004016104aa9190613cb3565b50604051635595a8fb60e11b81526001600160a01b03868116600483015284169063ab2b51f690602401600060405180830381600087803b1580156115a557600080fd5b505af11580156115b9573d6000803e3d6000fd5b505060405163c44b11f760e01b81526001600160a01b038881166004830152600093508616915063c44b11f790602401602060405180830381865afa158015611606573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162a9190613d8a565b90506116368186613517565b8051604051635c69493b60e11b81526001600160a01b03888116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b15801561168457600080fd5b505af1158015611698573d6000803e3d6000fd5b5050604051634c63ed2760e11b81526001600160a01b038981166004830152871692506398c7da4e9150602401600060405180830381600087803b1580156116df57600080fd5b505af11580156116f3573d6000803e3d6000fd5b50505050856001600160a01b03167fb1cee61cb39a5e7ac50acc4d8a1de7e4a6cf7cd7c6c9c69349becdc72a60e21c8660405161173291815260200190565b60405180910390a2505050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015611790573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b49190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015611802573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118269190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906118695760405162461bcd60e51b81526004016104aa9190613cb3565b506034546040516365558ae560e11b81526001600160a01b038581166004830152600092169063caab15ca90602401602060405180830381865afa1580156118b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d99190613c6d565b60345460405163a8cd5d0f60e01b8152600481018390526001600160a01b03888116602483015292935091169063a8cd5d0f906044015b600060405180830381600087803b15801561192a57600080fd5b505af115801561193e573d6000803e3d6000fd5b505050505050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015611992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b69190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906119f95760405162461bcd60e51b81526004016104aa9190613cb3565b50603454604051637a993c9960e01b81526001600160a01b03838116600483015290911690637a993c9990602401600060405180830381600087803b158015611a4157600080fd5b505af1158015611a55573d6000803e3d6000fd5b5050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015611aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ace9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015611b1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b409190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090611b835760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0388811660048301526000919085169063c44b11f790602401602060405180830381865afa158015611bce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf29190613d8a565b90508587111560405180604001604052806002815260200161323560f01b81525090611c315760405162461bcd60e51b81526004016104aa9190613cb3565b508515611cc257604080518082019091526002815261323560f01b60208201526127108611611c735760405162461bcd60e51b81526004016104aa9190613cb3565b50612710611c818787613570565b111560405180604001604052806002815260200161323560f01b81525090611cbc5760405162461bcd60e51b81526004016104aa9190613cb3565b50611d05565b604080518082019091526002815261323560f01b60208201528515611cfa5760405162461bcd60e51b81526004016104aa9190613cb3565b50611d058885613620565b611d0f818861384a565b611d198187613893565b611d2381866138e4565b8051604051635c69493b60e11b81526001600160a01b038a8116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b158015611d7157600080fd5b505af1158015611d85573d6000803e3d6000fd5b5050604080518a8152602081018a90529081018890526001600160a01b038b1692507f637febbda9275aea2e85c0ff690444c8d87eb2e8339bbede9715abcc89cb0995915060600160405180910390a25050505050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015611e2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e519190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec39190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090611f065760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa158015611f51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f759190613d8a565b9050611f828160016130b2565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b50506040516001600160a01b03881692507f9f32a339ab4590ec0a60d629f2322805ba6e57c9d862e1ef9f8555f6780ea2c69150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa15801561206c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120909190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906120d35760405162461bcd60e51b81526004016104aa9190613cb3565b50604051635595a8fb60e11b81526001600160a01b03848116600483015282169063ab2b51f690602401600060405180830381600087803b15801561211757600080fd5b505af115801561212b573d6000803e3d6000fd5b5050603454604051633d726f3d60e01b81526001600160a01b0387811660048301528581166024830152604482018790529091169250633d726f3d9150606401600060405180830381600087803b15801561218557600080fd5b505af1158015612199573d6000803e3d6000fd5b5050604051634c63ed2760e11b81526001600160a01b038681166004830152841692506398c7da4e9150602401600060405180830381600087803b1580156121e057600080fd5b505af11580156121f4573d6000803e3d6000fd5b50505050806001600160a01b0316836001600160a01b03167f9f19c6c51bb8807ea24ad68677521ee3c166f9a3e5f3b882c81ddd70cf901c0f8460405161223d91815260200190565b60405180910390a3505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015612298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bc9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa15801561230a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906123715760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa1580156123bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e09190613d8a565b90506123ed816001613937565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b15801561243b57600080fd5b505af115801561244f573d6000803e3d6000fd5b50506040516001600160a01b03881692507f35b80cd8ea3440e9a8454f116fa658b858da1b64c86c48451f4559cefcdfb56c9150600090a25050505050565b6001805460ff168061249f5750303b155b806124ab575060005481115b61251d5760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a656400000000000000000000000000000000000060648201526084016104aa565b60015460ff1615801561253c576001805460ff19168117905560008290555b6034805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385161790558015612575576001805460ff191690555b505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa1580156125c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ec9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa15801561263a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906126a15760405162461bcd60e51b81526004016104aa9190613cb3565b506126ac8484613620565b60405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa1580156126f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061271a9190613d8a565b9050612727816000613937565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b15801561277557600080fd5b505af1158015612789573d6000803e3d6000fd5b50506040516001600160a01b03881692507f6f60cf8bd0f218cabe1ea3150bd07b0b758c35c4cfdf7138017a283e65564d5e9150600090a25050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015612816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283a9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015612888573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128ac9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906128ef5760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa15801561293a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061295e9190613d8a565b905061296b8160006134e9565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b1580156129b957600080fd5b505af11580156129cd573d6000803e3d6000fd5b50506040516001600160a01b03881692507f555c6ca779f1bc723a46db471ebfda58660eb8f99beaf703fbb51971d7413d689150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015612a55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a799190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090612abc5760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163774b095f60e01b81526001600160a01b038481166004830152838116602483015282169063774b095f90604401600060405180830381600087803b158015612b0857600080fd5b505af1158015612b1c573d6000803e3d6000fd5b50505050505050565b60345460408051636ee554f560e11b8152905133926001600160a01b03169163ddcaa9ea9160048083019260209291908290030181865afa158015612b6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b929190613c96565b6001600160a01b03161460405180604001604052806002815260200161191b60f11b81525090612bd55760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163bedb86fb60e01b815282151560048201526001600160a01b0382169063bedb86fb906024015b600060405180830381600087803b158015612c1a57600080fd5b505af1158015612c2e573d6000803e3d6000fd5b505050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015612c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca39190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090612ce65760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0384811660048301526000919083169063c44b11f790602401602060405180830381865afa158015612d31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d559190613d8a565b9050612d618184613965565b8051604051635c69493b60e11b81526001600160a01b03868116600483015260248201929092529083169063b8d2927690604401600060405180830381600087803b158015612daf57600080fd5b505af1158015612dc3573d6000803e3d6000fd5b50505050836001600160a01b03167f6055c6b98453afba127434205f3042a7d1ff206e70a9cd3f961348d97142a76d84604051610b8c91815260200190565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015612e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6f9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090612eb25760405162461bcd60e51b81526004016104aa9190613cb3565b50604051637cde5bfd60e11b8152600481018390526001600160a01b0382169063f9bcb7fa90602401612c00565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015612f2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f529190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015612fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fc49190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906130075760405162461bcd60e51b81526004016104aa9190613cb3565b506034546040516365558ae560e11b81526001600160a01b038581166004830152600092169063caab15ca90602401602060405180830381865afa158015613053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130779190613c6d565b603454604051635666be1d60e11b8152600481018390526001600160a01b03888116602483015292935091169063accd7c3a90604401611910565b603a816130c05760006130c3565b60015b8351670400000000000000191660ff9190911690911b1790915250565b6039816130ee5760006130f1565b60015b8351670200000000000000191660ff9190911690911b1790915250565b6034546040516304b0708d60e11b81526001600160a01b0384811660048301526000921690630960e11a90602401602060405180830381865afa158015613159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061317d9190613c96565b90506000806001600160a01b038316634dc91c606131a16060870160408801613ba2565b6131ae6060880188613ddc565b6131bb60808a018a613ddc565b6131c860208c018c613e39565b6040518763ffffffff1660e01b81526004016131e996959493929190613e7f565b6060604051808303816000875af1158015613208573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322c9190613ecc565b5090925090506001600160a01b0385166317293feb6132516060870160408801613ba2565b85858561326460408b0160208c01613ba2565b60405160e087901b6001600160e01b03191681526001600160a01b039586166004820152938516602485015260448401929092526064830152909116608482015260a401600060405180830381600087803b1580156132c257600080fd5b505af11580156132d6573d6000803e3d6000fd5b506000925050506001600160a01b03861663c44b11f76132fc6060880160408901613ba2565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613340573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133649190613d8a565b90506133806133766020870187613e39565b829060ff166139ce565b61338b816001613937565b6133968160006130e0565b6133a18160016134e9565b6001600160a01b03861663b8d292766133c06060880160408901613ba2565b835160405160e084901b6001600160e01b03191681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561340857600080fd5b505af115801561341c573d6000803e3d6000fd5b5050505081838660400160208101906134359190613ba2565b6001600160a01b03167f483a9b58bd357adf72b547f9a568369a51739509d416aa7d8b5cb46d3815212d61346f60408a0160208b01613ba2565b6040516001600160a01b03909116815260200160405180910390a4505050505050565b604080518082019091526002815261383360f01b6020820152610fa08211156134ce5760405162461bcd60e51b81526004016104aa9190613cb3565b508151690ffff0000000000000001916603c9190911b179052565b603b816134f75760006134fa565b60015b8351670800000000000000191660ff9190911690911b1790915250565b604080518082019091526002815261383360f01b6020820152610fa08211156135535760405162461bcd60e51b81526004016104aa9190613cb3565b5081516b0ffff00000000000000000001916604c9190911b179052565b600082158061357d575081155b1561358a5750600061361a565b816135986002612710613f10565b6135a490600019613f32565b6135ae9190613f10565b83111560405180604001604052806002815260200161199960f11b815250906135ea5760405162461bcd60e51b81526004016104aa9190613cb3565b506127106135f9600282613f10565b6136038486613f45565b61360d9190613f5c565b6136179190613f10565b90505b92915050565b6040516335ea6a7560e01b81526001600160a01b038381166004830152600091908316906335ea6a759060240161016060405180830381865afa15801561366b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061368f9190613f9a565b60c081015160405163cc899b9d60e01b81526001600160a01b0386811660048301529293509091600091829184169063cc899b9d90602401606060405180830381865afa1580156136e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137089190613ecc565b50604051634938448d60e11b81526004810183905291935091506000906001600160a01b03851690639270891a90602401602060405180830381865afa158015613756573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377a9190613c6d565b1580156137ed5750604051634938448d60e11b8152600481018390526001600160a01b03851690639270891a90602401602060405180830381865afa1580156137c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137eb9190613c6d565b155b9050808015613807575060608501516001600160801b0316155b604051806040016040528060028152602001610c8d60f21b815250906138405760405162461bcd60e51b81526004016104aa9190613cb3565b5050505050505050565b604080518082019091526002815261373960f01b602082015261ffff8211156138865760405162461bcd60e51b81526004016104aa9190613cb3565b50815161ffff1916179052565b604080518082019091526002815261038360f41b602082015261ffff8211156138cf5760405162461bcd60e51b81526004016104aa9190613cb3565b50815163ffff0000191660109190911b179052565b604080518082019091526002815261383160f01b602082015261ffff8211156139205760405162461bcd60e51b81526004016104aa9190613cb3565b50815165ffff00000000191660209190911b179052565b603881613945576000613948565b60015b8351670100000000000000191660ff9190911690911b1790915250565b6040805180820190915260028152610e0d60f21b602082015268ffffffffffffffffff8211156139a85760405162461bcd60e51b81526004016104aa9190613cb3565b508151740ffffffffffffffffff000000000000000000000001916605c9190911b179052565b6040805180820190915260028152611c1960f11b602082015260ff821115613a095760405162461bcd60e51b81526004016104aa9190613cb3565b50815166ff000000000000191660309190911b179052565b6001600160a01b0381168114613a3657600080fd5b50565b60008060408385031215613a4c57600080fd5b8235613a5781613a21565b91506020830135613a6781613a21565b809150509250929050565b600080600060408486031215613a8757600080fd5b833567ffffffffffffffff80821115613a9f57600080fd5b818601915086601f830112613ab357600080fd5b813581811115613ac257600080fd5b8760208260051b8501011115613ad757600080fd5b60209283019550935050840135613aed81613a21565b809150509250925092565b600080600060608486031215613b0d57600080fd5b8335613b1881613a21565b9250602084013591506040840135613aed81613a21565b600080600060608486031215613b4457600080fd5b8335613b4f81613a21565b92506020840135613b5f81613a21565b91506040840135613aed81613a21565b6001600160801b0381168114613a3657600080fd5b60008060408385031215613b9757600080fd5b8235613a5781613b6f565b600060208284031215613bb457600080fd5b8135613bbf81613a21565b9392505050565b600080600080600060a08688031215613bde57600080fd5b8535613be981613a21565b94506020860135935060408601359250606086013591506080860135613c0e81613a21565b809150509295509295909350565b8015158114613a3657600080fd5b60008060408385031215613c3d57600080fd5b8235613a5781613c1c565b60008060408385031215613c5b57600080fd5b823591506020830135613a6781613a21565b600060208284031215613c7f57600080fd5b5051919050565b8051613c9181613a21565b919050565b600060208284031215613ca857600080fd5b8151613bbf81613a21565b60006020808352835180602085015260005b81811015613ce157858101830151858201604001528201613cc5565b506000604082860101526040601f19601f8301168501019250505092915050565b604051610160810167ffffffffffffffff81118282101715613d3457634e487b7160e01b600052604160045260246000fd5b60405290565b600060208284031215613d4c57600080fd5b6040516020810181811067ffffffffffffffff82111715613d7d57634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b600060208284031215613d9c57600080fd5b6136178383613d3a565b634e487b7160e01b600052603260045260246000fd5b60008235609e19833603018112613dd257600080fd5b9190910192915050565b6000808335601e19843603018112613df357600080fd5b83018035915067ffffffffffffffff821115613e0e57600080fd5b602001915036819003821315613e2357600080fd5b9250929050565b60ff81168114613a3657600080fd5b600060208284031215613e4b57600080fd5b8135613bbf81613e2a565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0387168152608060208201526000613ea2608083018789613e56565b8281036040840152613eb5818688613e56565b91505060ff83166060830152979650505050505050565b600080600060608486031215613ee157600080fd5b83519250602084015191506040840151613aed81613c1c565b634e487b7160e01b600052601160045260246000fd5b600082613f2d57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561361a5761361a613efa565b808202811582820484141761361a5761361a613efa565b8082018082111561361a5761361a613efa565b8051613c9181613b6f565b805164ffffffffff81168114613c9157600080fd5b8051613c9181613e2a565b60006101608284031215613fad57600080fd5b613fb5613d02565b613fbf8484613d3a565b8152613fcd60208401613f6f565b6020820152613fde60408401613f6f565b6040820152613fef60608401613f6f565b606082015261400060808401613f6f565b608082015261401160a08401613f7a565b60a082015261402260c08401613c86565b60c082015260e083015160e082015261010080840151818301525061012061404b818501613c86565b9082015261014061405d848201613f8f565b90820152939250505056fea26469706673582212204eacc5d4610f74767cc00f53285a8cae31d3644cf12d55f6950fd93e65d42b7a64736f6c63430008170033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101985760003560e01c806391d77d71116100e3578063d006bc171161008c578063eb2f6b1f11610066578063eb2f6b1f1461034a578063fa3f8ff41461035d578063fe3d98431461037057600080fd5b8063d006bc1714610311578063d1680b6c14610324578063e65040bc1461033757600080fd5b8063c4d66de8116100bd578063c4d66de8146102bc578063c72c4d10146102cf578063c7864387146102fe57600080fd5b806391d77d71146102835780639892f75914610296578063bf81672f146102a957600080fd5b8063517f63dc11610145578063787203881161011f578063787203881461024a5780637a993c991461025d5780638b9cea7c1461027057600080fd5b8063517f63dc1461021157806370c3eb3114610224578063773a66571461023757600080fd5b806346f39cf31161017657806346f39cf3146101d85780634782a367146101eb57806348fca5a6146101fe57600080fd5b806318ce73e71461019d57806318e13279146101b257806325d2ca51146101c5575b600080fd5b6101b06101ab366004613a39565b610383565b005b6101b06101c0366004613a39565b6105d0565b6101b06101d3366004613a72565b610814565b6101b06101e6366004613af8565b61090b565b6101b06101f9366004613a39565b610b9a565b6101b061020c366004613b2f565b610dde565b6101b061021f366004613a39565b610fed565b6101b0610232366004613b84565b611231565b6101b0610245366004613af8565b61143a565b6101b0610258366004613a39565b611742565b6101b061026b366004613ba2565b611949565b6101b061027e366004613bc6565b611a5c565b6101b0610291366004613a39565b611ddf565b6101b06102a4366004613af8565b612023565b6101b06102b7366004613a39565b61224a565b6101b06102ca366004613ba2565b61248e565b6034546102e2906001600160a01b031681565b6040516001600160a01b03909116815260200160405180910390f35b6101b061030c366004613a39565b61257a565b6101b061031f366004613a39565b6127c8565b6101b0610332366004613b2f565b612a0c565b6101b0610345366004613c2a565b612b25565b6101b0610358366004613af8565b612c36565b6101b061036b366004613c48565b612e02565b6101b061037e366004613a39565b612ee0565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa1580156103d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f59190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015610443573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104679190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906104b35760405162461bcd60e51b81526004016104aa9190613cb3565b60405180910390fd5b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa1580156104fe573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105229190613d8a565b905061052f8160006130b2565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b15801561057d57600080fd5b505af1158015610591573d6000803e3d6000fd5b50506040516001600160a01b03881692507fe9a7e5fd4fc8ea18e602350324bf48e8f05d12434af0ce0be05743e6a5fdcb9e9150600090a25050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa15801561061e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106429190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015610690573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b49190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906106f75760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa158015610742573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107669190613d8a565b90506107738160016130e0565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b1580156107c157600080fd5b505af11580156107d5573d6000803e3d6000fd5b50506040516001600160a01b03881692507f85dc710add8a0914461a7dc5a63f6fc529a7700f8c6089a3faf5e93256ccf12a9150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa15801561085d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108819190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906108c45760405162461bcd60e51b81526004016104aa9190613cb3565b5060005b82811015610905576108fd828585848181106108e6576108e6613da6565b90506020028101906108f89190613dbc565b61310e565b6001016108c8565b50505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015610954573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109789190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906109bb5760405162461bcd60e51b81526004016104aa9190613cb3565b50604051635595a8fb60e11b81526001600160a01b03848116600483015282169063ab2b51f690602401600060405180830381600087803b1580156109ff57600080fd5b505af1158015610a13573d6000803e3d6000fd5b505060405163c44b11f760e01b81526001600160a01b038681166004830152600093508416915063c44b11f790602401602060405180830381865afa158015610a60573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a849190613d8a565b9050610a908184613492565b8051604051635c69493b60e11b81526001600160a01b03868116600483015260248201929092529083169063b8d2927690604401600060405180830381600087803b158015610ade57600080fd5b505af1158015610af2573d6000803e3d6000fd5b5050604051634c63ed2760e11b81526001600160a01b038781166004830152851692506398c7da4e9150602401600060405180830381600087803b158015610b3957600080fd5b505af1158015610b4d573d6000803e3d6000fd5b50505050836001600160a01b03167fee3084d98b631d079c0b340ac21f6851def11a0ef269af72ad049756e5de874084604051610b8c91815260200190565b60405180910390a250505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015610be8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c0c9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015610c5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090610cc15760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa158015610d0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d309190613d8a565b9050610d3d8160006130e0565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b158015610d8b57600080fd5b505af1158015610d9f573d6000803e3d6000fd5b50506040516001600160a01b03881692507f838ecdc4709a31a26db48b0c853212cedde3f725f07030079d793fb0719647609150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015610e27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4b9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090610e8e5760405162461bcd60e51b81526004016104aa9190613cb3565b50604051635595a8fb60e11b81526001600160a01b03848116600483015282169063ab2b51f690602401600060405180830381600087803b158015610ed257600080fd5b505af1158015610ee6573d6000803e3d6000fd5b5050604051631d2118f960e01b81526001600160a01b038681166004830152858116602483015284169250631d2118f99150604401600060405180830381600087803b158015610f3557600080fd5b505af1158015610f49573d6000803e3d6000fd5b5050604051634c63ed2760e11b81526001600160a01b038681166004830152841692506398c7da4e9150602401600060405180830381600087803b158015610f9057600080fd5b505af1158015610fa4573d6000803e3d6000fd5b50506040516001600160a01b038581168252861692507f5644b64ebb0ce18c4032248ca52f58355469092ff072866c3dcd8640e817d6a5915060200160405180910390a2505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa15801561103b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061105f9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa1580156110ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d19190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906111145760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa15801561115f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111839190613d8a565b90506111908160016134e9565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b1580156111de57600080fd5b505af11580156111f2573d6000803e3d6000fd5b50506040516001600160a01b03881692507f42924e374f01dd5c0b51fa6ab454551ccf573844ad021001faec9b97efa22db69150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa15801561127a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906112e15760405162461bcd60e51b81526004016104aa9190613cb3565b50604080518082019091526002815261323760f01b60208201526127106001600160801b03841611156113275760405162461bcd60e51b81526004016104aa9190613cb3565b506000816001600160a01b031663074b2e436040518163ffffffff1660e01b8152600401602060405180830381865afa158015611368573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061138c9190613c6d565b604051636bb040f160e11b81526001600160801b03851660048201529091506001600160a01b0383169063d76081e290602401600060405180830381600087803b1580156113d957600080fd5b505af11580156113ed573d6000803e3d6000fd5b5050604080516001600160801b038086168252871660208201527f71aba182c9d0529b516de7a78bed74d49c207ef7e152f52f7ea5d8730138f643935001905060405180910390a1505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015611488573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ac9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa1580156114fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061151e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906115615760405162461bcd60e51b81526004016104aa9190613cb3565b50604051635595a8fb60e11b81526001600160a01b03868116600483015284169063ab2b51f690602401600060405180830381600087803b1580156115a557600080fd5b505af11580156115b9573d6000803e3d6000fd5b505060405163c44b11f760e01b81526001600160a01b038881166004830152600093508616915063c44b11f790602401602060405180830381865afa158015611606573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061162a9190613d8a565b90506116368186613517565b8051604051635c69493b60e11b81526001600160a01b03888116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b15801561168457600080fd5b505af1158015611698573d6000803e3d6000fd5b5050604051634c63ed2760e11b81526001600160a01b038981166004830152871692506398c7da4e9150602401600060405180830381600087803b1580156116df57600080fd5b505af11580156116f3573d6000803e3d6000fd5b50505050856001600160a01b03167fb1cee61cb39a5e7ac50acc4d8a1de7e4a6cf7cd7c6c9c69349becdc72a60e21c8660405161173291815260200190565b60405180910390a2505050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015611790573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117b49190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015611802573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118269190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906118695760405162461bcd60e51b81526004016104aa9190613cb3565b506034546040516365558ae560e11b81526001600160a01b038581166004830152600092169063caab15ca90602401602060405180830381865afa1580156118b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d99190613c6d565b60345460405163a8cd5d0f60e01b8152600481018390526001600160a01b03888116602483015292935091169063a8cd5d0f906044015b600060405180830381600087803b15801561192a57600080fd5b505af115801561193e573d6000803e3d6000fd5b505050505050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015611992573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b69190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906119f95760405162461bcd60e51b81526004016104aa9190613cb3565b50603454604051637a993c9960e01b81526001600160a01b03838116600483015290911690637a993c9990602401600060405180830381600087803b158015611a4157600080fd5b505af1158015611a55573d6000803e3d6000fd5b5050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015611aaa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ace9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015611b1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b409190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090611b835760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0388811660048301526000919085169063c44b11f790602401602060405180830381865afa158015611bce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf29190613d8a565b90508587111560405180604001604052806002815260200161323560f01b81525090611c315760405162461bcd60e51b81526004016104aa9190613cb3565b508515611cc257604080518082019091526002815261323560f01b60208201526127108611611c735760405162461bcd60e51b81526004016104aa9190613cb3565b50612710611c818787613570565b111560405180604001604052806002815260200161323560f01b81525090611cbc5760405162461bcd60e51b81526004016104aa9190613cb3565b50611d05565b604080518082019091526002815261323560f01b60208201528515611cfa5760405162461bcd60e51b81526004016104aa9190613cb3565b50611d058885613620565b611d0f818861384a565b611d198187613893565b611d2381866138e4565b8051604051635c69493b60e11b81526001600160a01b038a8116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b158015611d7157600080fd5b505af1158015611d85573d6000803e3d6000fd5b5050604080518a8152602081018a90529081018890526001600160a01b038b1692507f637febbda9275aea2e85c0ff690444c8d87eb2e8339bbede9715abcc89cb0995915060600160405180910390a25050505050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015611e2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e519190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015611e9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ec39190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090611f065760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa158015611f51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f759190613d8a565b9050611f828160016130b2565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b158015611fd057600080fd5b505af1158015611fe4573d6000803e3d6000fd5b50506040516001600160a01b03881692507f9f32a339ab4590ec0a60d629f2322805ba6e57c9d862e1ef9f8555f6780ea2c69150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa15801561206c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120909190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906120d35760405162461bcd60e51b81526004016104aa9190613cb3565b50604051635595a8fb60e11b81526001600160a01b03848116600483015282169063ab2b51f690602401600060405180830381600087803b15801561211757600080fd5b505af115801561212b573d6000803e3d6000fd5b5050603454604051633d726f3d60e01b81526001600160a01b0387811660048301528581166024830152604482018790529091169250633d726f3d9150606401600060405180830381600087803b15801561218557600080fd5b505af1158015612199573d6000803e3d6000fd5b5050604051634c63ed2760e11b81526001600160a01b038681166004830152841692506398c7da4e9150602401600060405180830381600087803b1580156121e057600080fd5b505af11580156121f4573d6000803e3d6000fd5b50505050806001600160a01b0316836001600160a01b03167f9f19c6c51bb8807ea24ad68677521ee3c166f9a3e5f3b882c81ddd70cf901c0f8460405161223d91815260200190565b60405180910390a3505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015612298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bc9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa15801561230a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906123715760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa1580156123bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e09190613d8a565b90506123ed816001613937565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b15801561243b57600080fd5b505af115801561244f573d6000803e3d6000fd5b50506040516001600160a01b03881692507f35b80cd8ea3440e9a8454f116fa658b858da1b64c86c48451f4559cefcdfb56c9150600090a25050505050565b6001805460ff168061249f5750303b155b806124ab575060005481115b61251d5760405162461bcd60e51b815260206004820152602e60248201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560448201527f656e20696e697469616c697a656400000000000000000000000000000000000060648201526084016104aa565b60015460ff1615801561253c576001805460ff19168117905560008290555b6034805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0385161790558015612575576001805460ff191690555b505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa1580156125c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ec9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa15801561263a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061265e9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906126a15760405162461bcd60e51b81526004016104aa9190613cb3565b506126ac8484613620565b60405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa1580156126f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061271a9190613d8a565b9050612727816000613937565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b15801561277557600080fd5b505af1158015612789573d6000803e3d6000fd5b50506040516001600160a01b03881692507f6f60cf8bd0f218cabe1ea3150bd07b0b758c35c4cfdf7138017a283e65564d5e9150600090a25050505050565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015612816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061283a9190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015612888573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128ac9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906128ef5760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0385811660048301526000919085169063c44b11f790602401602060405180830381865afa15801561293a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061295e9190613d8a565b905061296b8160006134e9565b8051604051635c69493b60e11b81526001600160a01b03878116600483015260248201929092529085169063b8d2927690604401600060405180830381600087803b1580156129b957600080fd5b505af11580156129cd573d6000803e3d6000fd5b50506040516001600160a01b03881692507f555c6ca779f1bc723a46db471ebfda58660eb8f99beaf703fbb51971d7413d689150600090a25050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015612a55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a799190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090612abc5760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163774b095f60e01b81526001600160a01b038481166004830152838116602483015282169063774b095f90604401600060405180830381600087803b158015612b0857600080fd5b505af1158015612b1c573d6000803e3d6000fd5b50505050505050565b60345460408051636ee554f560e11b8152905133926001600160a01b03169163ddcaa9ea9160048083019260209291908290030181865afa158015612b6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b929190613c96565b6001600160a01b03161460405180604001604052806002815260200161191b60f11b81525090612bd55760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163bedb86fb60e01b815282151560048201526001600160a01b0382169063bedb86fb906024015b600060405180830381600087803b158015612c1a57600080fd5b505af1158015612c2e573d6000803e3d6000fd5b505050505050565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015612c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca39190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090612ce65760405162461bcd60e51b81526004016104aa9190613cb3565b5060405163c44b11f760e01b81526001600160a01b0384811660048301526000919083169063c44b11f790602401602060405180830381865afa158015612d31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d559190613d8a565b9050612d618184613965565b8051604051635c69493b60e11b81526001600160a01b03868116600483015260248201929092529083169063b8d2927690604401600060405180830381600087803b158015612daf57600080fd5b505af1158015612dc3573d6000803e3d6000fd5b50505050836001600160a01b03167f6055c6b98453afba127434205f3042a7d1ff206e70a9cd3f961348d97142a76d84604051610b8c91815260200190565b603454604080516306e6fd7360e11b8152905133926001600160a01b031691630dcdfae69160048083019260209291908290030181865afa158015612e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6f9190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b81525090612eb25760405162461bcd60e51b81526004016104aa9190613cb3565b50604051637cde5bfd60e11b8152600481018390526001600160a01b0382169063f9bcb7fa90602401612c00565b6034546040516365558ae560e11b81526001600160a01b038084166004830152839260009291169063caab15ca90602401602060405180830381865afa158015612f2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f529190613c6d565b603454604051633553f60d60e01b81526004810183905291925033916001600160a01b0390911690633553f60d90602401602060405180830381865afa158015612fa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fc49190613c96565b6001600160a01b03161460405180604001604052806002815260200161323160f01b815250906130075760405162461bcd60e51b81526004016104aa9190613cb3565b506034546040516365558ae560e11b81526001600160a01b038581166004830152600092169063caab15ca90602401602060405180830381865afa158015613053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130779190613c6d565b603454604051635666be1d60e11b8152600481018390526001600160a01b03888116602483015292935091169063accd7c3a90604401611910565b603a816130c05760006130c3565b60015b8351670400000000000000191660ff9190911690911b1790915250565b6039816130ee5760006130f1565b60015b8351670200000000000000191660ff9190911690911b1790915250565b6034546040516304b0708d60e11b81526001600160a01b0384811660048301526000921690630960e11a90602401602060405180830381865afa158015613159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061317d9190613c96565b90506000806001600160a01b038316634dc91c606131a16060870160408801613ba2565b6131ae6060880188613ddc565b6131bb60808a018a613ddc565b6131c860208c018c613e39565b6040518763ffffffff1660e01b81526004016131e996959493929190613e7f565b6060604051808303816000875af1158015613208573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061322c9190613ecc565b5090925090506001600160a01b0385166317293feb6132516060870160408801613ba2565b85858561326460408b0160208c01613ba2565b60405160e087901b6001600160e01b03191681526001600160a01b039586166004820152938516602485015260448401929092526064830152909116608482015260a401600060405180830381600087803b1580156132c257600080fd5b505af11580156132d6573d6000803e3d6000fd5b506000925050506001600160a01b03861663c44b11f76132fc6060880160408901613ba2565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015613340573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133649190613d8a565b90506133806133766020870187613e39565b829060ff166139ce565b61338b816001613937565b6133968160006130e0565b6133a18160016134e9565b6001600160a01b03861663b8d292766133c06060880160408901613ba2565b835160405160e084901b6001600160e01b03191681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561340857600080fd5b505af115801561341c573d6000803e3d6000fd5b5050505081838660400160208101906134359190613ba2565b6001600160a01b03167f483a9b58bd357adf72b547f9a568369a51739509d416aa7d8b5cb46d3815212d61346f60408a0160208b01613ba2565b6040516001600160a01b03909116815260200160405180910390a4505050505050565b604080518082019091526002815261383360f01b6020820152610fa08211156134ce5760405162461bcd60e51b81526004016104aa9190613cb3565b508151690ffff0000000000000001916603c9190911b179052565b603b816134f75760006134fa565b60015b8351670800000000000000191660ff9190911690911b1790915250565b604080518082019091526002815261383360f01b6020820152610fa08211156135535760405162461bcd60e51b81526004016104aa9190613cb3565b5081516b0ffff00000000000000000001916604c9190911b179052565b600082158061357d575081155b1561358a5750600061361a565b816135986002612710613f10565b6135a490600019613f32565b6135ae9190613f10565b83111560405180604001604052806002815260200161199960f11b815250906135ea5760405162461bcd60e51b81526004016104aa9190613cb3565b506127106135f9600282613f10565b6136038486613f45565b61360d9190613f5c565b6136179190613f10565b90505b92915050565b6040516335ea6a7560e01b81526001600160a01b038381166004830152600091908316906335ea6a759060240161016060405180830381865afa15801561366b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061368f9190613f9a565b60c081015160405163cc899b9d60e01b81526001600160a01b0386811660048301529293509091600091829184169063cc899b9d90602401606060405180830381865afa1580156136e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137089190613ecc565b50604051634938448d60e11b81526004810183905291935091506000906001600160a01b03851690639270891a90602401602060405180830381865afa158015613756573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061377a9190613c6d565b1580156137ed5750604051634938448d60e11b8152600481018390526001600160a01b03851690639270891a90602401602060405180830381865afa1580156137c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137eb9190613c6d565b155b9050808015613807575060608501516001600160801b0316155b604051806040016040528060028152602001610c8d60f21b815250906138405760405162461bcd60e51b81526004016104aa9190613cb3565b5050505050505050565b604080518082019091526002815261373960f01b602082015261ffff8211156138865760405162461bcd60e51b81526004016104aa9190613cb3565b50815161ffff1916179052565b604080518082019091526002815261038360f41b602082015261ffff8211156138cf5760405162461bcd60e51b81526004016104aa9190613cb3565b50815163ffff0000191660109190911b179052565b604080518082019091526002815261383160f01b602082015261ffff8211156139205760405162461bcd60e51b81526004016104aa9190613cb3565b50815165ffff00000000191660209190911b179052565b603881613945576000613948565b60015b8351670100000000000000191660ff9190911690911b1790915250565b6040805180820190915260028152610e0d60f21b602082015268ffffffffffffffffff8211156139a85760405162461bcd60e51b81526004016104aa9190613cb3565b508151740ffffffffffffffffff000000000000000000000001916605c9190911b179052565b6040805180820190915260028152611c1960f11b602082015260ff821115613a095760405162461bcd60e51b81526004016104aa9190613cb3565b50815166ff000000000000191660309190911b179052565b6001600160a01b0381168114613a3657600080fd5b50565b60008060408385031215613a4c57600080fd5b8235613a5781613a21565b91506020830135613a6781613a21565b809150509250929050565b600080600060408486031215613a8757600080fd5b833567ffffffffffffffff80821115613a9f57600080fd5b818601915086601f830112613ab357600080fd5b813581811115613ac257600080fd5b8760208260051b8501011115613ad757600080fd5b60209283019550935050840135613aed81613a21565b809150509250925092565b600080600060608486031215613b0d57600080fd5b8335613b1881613a21565b9250602084013591506040840135613aed81613a21565b600080600060608486031215613b4457600080fd5b8335613b4f81613a21565b92506020840135613b5f81613a21565b91506040840135613aed81613a21565b6001600160801b0381168114613a3657600080fd5b60008060408385031215613b9757600080fd5b8235613a5781613b6f565b600060208284031215613bb457600080fd5b8135613bbf81613a21565b9392505050565b600080600080600060a08688031215613bde57600080fd5b8535613be981613a21565b94506020860135935060408601359250606086013591506080860135613c0e81613a21565b809150509295509295909350565b8015158114613a3657600080fd5b60008060408385031215613c3d57600080fd5b8235613a5781613c1c565b60008060408385031215613c5b57600080fd5b823591506020830135613a6781613a21565b600060208284031215613c7f57600080fd5b5051919050565b8051613c9181613a21565b919050565b600060208284031215613ca857600080fd5b8151613bbf81613a21565b60006020808352835180602085015260005b81811015613ce157858101830151858201604001528201613cc5565b506000604082860101526040601f19601f8301168501019250505092915050565b604051610160810167ffffffffffffffff81118282101715613d3457634e487b7160e01b600052604160045260246000fd5b60405290565b600060208284031215613d4c57600080fd5b6040516020810181811067ffffffffffffffff82111715613d7d57634e487b7160e01b600052604160045260246000fd5b6040529151825250919050565b600060208284031215613d9c57600080fd5b6136178383613d3a565b634e487b7160e01b600052603260045260246000fd5b60008235609e19833603018112613dd257600080fd5b9190910192915050565b6000808335601e19843603018112613df357600080fd5b83018035915067ffffffffffffffff821115613e0e57600080fd5b602001915036819003821315613e2357600080fd5b9250929050565b60ff81168114613a3657600080fd5b600060208284031215613e4b57600080fd5b8135613bbf81613e2a565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0387168152608060208201526000613ea2608083018789613e56565b8281036040840152613eb5818688613e56565b91505060ff83166060830152979650505050505050565b600080600060608486031215613ee157600080fd5b83519250602084015191506040840151613aed81613c1c565b634e487b7160e01b600052601160045260246000fd5b600082613f2d57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561361a5761361a613efa565b808202811582820484141761361a5761361a613efa565b8082018082111561361a5761361a613efa565b8051613c9181613b6f565b805164ffffffffff81168114613c9157600080fd5b8051613c9181613e2a565b60006101608284031215613fad57600080fd5b613fb5613d02565b613fbf8484613d3a565b8152613fcd60208401613f6f565b6020820152613fde60408401613f6f565b6040820152613fef60608401613f6f565b606082015261400060808401613f6f565b608082015261401160a08401613f7a565b60a082015261402260c08401613c86565b60c082015260e083015160e082015261010080840151818301525061012061404b818501613c86565b9082015261014061405d848201613f8f565b90820152939250505056fea26469706673582212204eacc5d4610f74767cc00f53285a8cae31d3644cf12d55f6950fd93e65d42b7a64736f6c63430008170033

Block Transaction Gas Used Reward
view all blocks sequenced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.