{"file_path":"contracts/CometWithExtendedAssetList.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometMainInterface.sol\";\nimport \"./IERC20NonStandard.sol\";\nimport \"./IPriceFeed.sol\";\nimport \"./IAssetListFactory.sol\";\nimport \"./IAssetListFactoryHolder.sol\";\nimport \"./IAssetList.sol\";\n\n/**\n * @title Compound's Comet Contract\n * @notice An efficient monolithic money market protocol\n * @author Compound\n */\ncontract CometWithExtendedAssetList is CometMainInterface {\n    /** General configuration constants **/\n\n    /// @notice The admin of the protocol\n    address public override immutable governor;\n\n    /// @notice The account which may trigger pauses\n    address public override immutable pauseGuardian;\n\n    /// @notice The address of the base token contract\n    address public override immutable baseToken;\n\n    /// @notice The address of the price feed for the base token\n    address public override immutable baseTokenPriceFeed;\n\n    /// @notice The address of the extension contract delegate\n    address public override immutable extensionDelegate;\n\n    /// @notice The point in the supply rates separating the low interest rate slope and the high interest rate slope (factor)\n    /// @dev uint64\n    uint public override immutable supplyKink;\n\n    /// @notice Per second supply interest rate slope applied when utilization is below kink (factor)\n    /// @dev uint64\n    uint public override immutable supplyPerSecondInterestRateSlopeLow;\n\n    /// @notice Per second supply interest rate slope applied when utilization is above kink (factor)\n    /// @dev uint64\n    uint public override immutable supplyPerSecondInterestRateSlopeHigh;\n\n    /// @notice Per second supply base interest rate (factor)\n    /// @dev uint64\n    uint public override immutable supplyPerSecondInterestRateBase;\n\n    /// @notice The point in the borrow rate separating the low interest rate slope and the high interest rate slope (factor)\n    /// @dev uint64\n    uint public override immutable borrowKink;\n\n    /// @notice Per second borrow interest rate slope applied when utilization is below kink (factor)\n    /// @dev uint64\n    uint public override immutable borrowPerSecondInterestRateSlopeLow;\n\n    /// @notice Per second borrow interest rate slope applied when utilization is above kink (factor)\n    /// @dev uint64\n    uint public override immutable borrowPerSecondInterestRateSlopeHigh;\n\n    /// @notice Per second borrow base interest rate (factor)\n    /// @dev uint64\n    uint public override immutable borrowPerSecondInterestRateBase;\n\n    /// @notice The fraction of the liquidation penalty that goes to buyers of collateral instead of the protocol\n    /// @dev uint64\n    uint public override immutable storeFrontPriceFactor;\n\n    /// @notice The scale for base token (must be less than 18 decimals)\n    /// @dev uint64\n    uint public override immutable baseScale;\n\n    /// @notice The scale for reward tracking\n    /// @dev uint64\n    uint public override immutable trackingIndexScale;\n\n    /// @notice The speed at which supply rewards are tracked (in trackingIndexScale)\n    /// @dev uint64\n    uint public override immutable baseTrackingSupplySpeed;\n\n    /// @notice The speed at which borrow rewards are tracked (in trackingIndexScale)\n    /// @dev uint64\n    uint public override immutable baseTrackingBorrowSpeed;\n\n    /// @notice The minimum amount of base principal wei for rewards to accrue\n    /// @dev This must be large enough so as to prevent division by base wei from overflowing the 64 bit indices\n    /// @dev uint104\n    uint public override immutable baseMinForRewards;\n\n    /// @notice The minimum base amount required to initiate a borrow\n    uint public override immutable baseBorrowMin;\n\n    /// @notice The minimum base token reserves which must be held before collateral is hodled\n    uint public override immutable targetReserves;\n\n    /// @notice The number of decimals for wrapped base token\n    uint8 public override immutable decimals;\n\n    /// @notice The number of assets this contract actually supports\n    uint8 public override immutable numAssets;\n\n    /// @notice Factor to divide by when accruing rewards in order to preserve 6 decimals (i.e. baseScale / 1e6)\n    uint internal immutable accrualDescaleFactor;\n    \n    /// @notice The address of the asset list\n    address immutable public assetList;\n\n    uint8 internal constant MAX_ASSETS_FOR_ASSET_LIST = 24;\n\n    /// @dev The protocol only supports 200% utilization on which borrows are allowed\n    /// It keeps healthy state of the market, with no over-utilization leading to illiquidity,\n    /// and keeps protocol reserves from exhaustion\n    uint256 public constant MAX_SUPPORTED_UTILIZATION = 2e18;\n\n    /**\n     * @notice Construct a new protocol instance\n     * @param config The mapping of initial/constant parameters\n     **/\n    constructor(Configuration memory config) {\n        // Sanity checks\n        uint8 decimals_ = IERC20NonStandard(config.baseToken).decimals();\n        if (decimals_ > MAX_BASE_DECIMALS) revert BadDecimals();\n        if (config.storeFrontPriceFactor > FACTOR_SCALE) revert BadDiscount();\n        if (config.assetConfigs.length > MAX_ASSETS_FOR_ASSET_LIST) revert TooManyAssets();\n        if (config.baseMinForRewards == 0) revert BadMinimum();\n        if (IPriceFeed(config.baseTokenPriceFeed).decimals() != PRICE_FEED_DECIMALS) revert BadDecimals();\n\n        // Copy configuration\n        unchecked {\n            governor = config.governor;\n            pauseGuardian = config.pauseGuardian;\n            baseToken = config.baseToken;\n            baseTokenPriceFeed = config.baseTokenPriceFeed;\n            extensionDelegate = config.extensionDelegate;\n            storeFrontPriceFactor = config.storeFrontPriceFactor;\n\n            decimals = decimals_;\n            baseScale = uint64(10 ** decimals_);\n            trackingIndexScale = config.trackingIndexScale;\n            if (baseScale < BASE_ACCRUAL_SCALE) revert BadDecimals();\n            accrualDescaleFactor = baseScale / BASE_ACCRUAL_SCALE;\n\n            baseMinForRewards = config.baseMinForRewards;\n            baseTrackingSupplySpeed = config.baseTrackingSupplySpeed;\n            baseTrackingBorrowSpeed = config.baseTrackingBorrowSpeed;\n\n            baseBorrowMin = config.baseBorrowMin;\n            targetReserves = config.targetReserves;\n        }\n\n        // Set interest rate model configs\n        unchecked {\n            supplyKink = config.supplyKink;\n            supplyPerSecondInterestRateSlopeLow = config.supplyPerYearInterestRateSlopeLow / SECONDS_PER_YEAR;\n            supplyPerSecondInterestRateSlopeHigh = config.supplyPerYearInterestRateSlopeHigh / SECONDS_PER_YEAR;\n            supplyPerSecondInterestRateBase = config.supplyPerYearInterestRateBase / SECONDS_PER_YEAR;\n            borrowKink = config.borrowKink;\n            borrowPerSecondInterestRateSlopeLow = config.borrowPerYearInterestRateSlopeLow / SECONDS_PER_YEAR;\n            borrowPerSecondInterestRateSlopeHigh = config.borrowPerYearInterestRateSlopeHigh / SECONDS_PER_YEAR;\n            borrowPerSecondInterestRateBase = config.borrowPerYearInterestRateBase / SECONDS_PER_YEAR;\n        }\n\n        // Set asset info\n        numAssets = uint8(config.assetConfigs.length);\n\n        assetList = IAssetListFactory(IAssetListFactoryHolder(extensionDelegate).assetListFactory()).createAssetList(config.assetConfigs);\n    }\n\n    /**\n     * @dev Prevents marked functions from being reentered \n     * Note: this restrict contracts from calling comet functions in their hooks.\n     * Doing so will cause the transaction to revert.\n     */\n    modifier nonReentrant() {\n        nonReentrantBefore();\n        _;\n        nonReentrantAfter();\n    }\n\n    /**\n     * @dev Checks that the reentrancy flag is not set and then sets the flag\n     */\n    function nonReentrantBefore() internal {\n        bytes32 slot = REENTRANCY_GUARD_FLAG_SLOT;\n        uint256 status;\n        assembly (\"memory-safe\") {\n            status := sload(slot)\n        }\n\n        if (status == REENTRANCY_GUARD_ENTERED) revert ReentrantCallBlocked();\n        assembly (\"memory-safe\") {\n            sstore(slot, REENTRANCY_GUARD_ENTERED)\n        }\n    }\n\n    /**\n     * @dev Unsets the reentrancy flag\n     */\n    function nonReentrantAfter() internal {\n        bytes32 slot = REENTRANCY_GUARD_FLAG_SLOT;\n        uint256 status;\n        assembly (\"memory-safe\") {\n            sstore(slot, REENTRANCY_GUARD_NOT_ENTERED)\n        }\n    }\n\n    /**\n     * @notice Initialize storage for the contract\n     * @dev Can be used from constructor or proxy\n     */\n    function initializeStorage() override external {\n        if (lastAccrualTime != 0) revert AlreadyInitialized();\n\n        // Initialize aggregates\n        lastAccrualTime = getNowInternal();\n        baseSupplyIndex = BASE_INDEX_SCALE;\n        baseBorrowIndex = BASE_INDEX_SCALE;\n\n        // Implicit initialization (not worth increasing contract size)\n        // trackingSupplyIndex = 0;\n        // trackingBorrowIndex = 0;\n    }\n\n    /**\n     * @notice Get the i-th asset info, according to the order they were passed in originally\n     * @param i The index of the asset info to get\n     * @return The asset info object\n     */\n    function getAssetInfo(uint8 i) override public view returns (AssetInfo memory) {\n        return IAssetList(assetList).getAssetInfo(i);\n    }\n\n    /**\n     * @dev Determine index of asset that matches given address\n     */\n    function getAssetInfoByAddress(address asset) override public view returns (AssetInfo memory) {\n        for (uint8 i = 0; i < numAssets; ) {\n            AssetInfo memory assetInfo = getAssetInfo(i);\n            if (assetInfo.asset == asset) {\n                return assetInfo;\n            }\n            unchecked { i++; }\n        }\n        revert BadAsset();\n    }\n\n    /**\n     * @return The current timestamp\n     **/\n    function getNowInternal() virtual internal view returns (uint40) {\n        if (block.timestamp >= 2**40) revert TimestampTooLarge();\n        return uint40(block.timestamp);\n    }\n\n    /**\n     * @dev Calculate accrued interest indices for base token supply and borrows\n     **/\n    function accruedInterestIndices(uint timeElapsed) internal view returns (uint64, uint64) {\n        uint64 baseSupplyIndex_ = baseSupplyIndex;\n        uint64 baseBorrowIndex_ = baseBorrowIndex;\n        if (timeElapsed > 0) {\n            uint utilization = getUtilization();\n            uint supplyRate = getSupplyRate(utilization);\n            uint borrowRate = getBorrowRate(utilization);\n            baseSupplyIndex_ += safe64(mulFactor(baseSupplyIndex_, supplyRate * timeElapsed));\n            baseBorrowIndex_ += safe64(mulFactor(baseBorrowIndex_, borrowRate * timeElapsed));\n        }\n\n        return (baseSupplyIndex_, baseBorrowIndex_);\n    }\n\n    /**\n     * @dev Accrue interest (and rewards) in base token supply and borrows\n     **/\n    function accrueInternal() internal {\n        uint40 now_ = getNowInternal();\n        uint timeElapsed = uint256(now_ - lastAccrualTime);\n        if (timeElapsed > 0) {\n            (baseSupplyIndex, baseBorrowIndex) = accruedInterestIndices(timeElapsed);\n            if (totalSupplyBase >= baseMinForRewards) {\n                trackingSupplyIndex += safe64(divBaseWei(baseTrackingSupplySpeed * timeElapsed, totalSupplyBase));\n            }\n            if (totalBorrowBase >= baseMinForRewards) {\n                trackingBorrowIndex += safe64(divBaseWei(baseTrackingBorrowSpeed * timeElapsed, totalBorrowBase));\n            }\n            lastAccrualTime = now_;\n        }\n    }\n\n    /**\n     * @dev Accrue interest and rewards for an account\n     * @param account The account to accrue interest and rewards for\n     * @dev Function is internal to allow accrual for account inside supplying, transferring and borrowing collateral functions\n     */\n    function accrueAccountInternal(address account) internal {\n        accrueInternal();\n\n        UserBasic memory basic = userBasic[account];\n        updateBasePrincipal(account, basic, basic.principal);\n    }\n\n    /**\n     * @notice Accrue interest and rewards for an account\n     * @param account The account to accrue interest and rewards for\n     * @dev This function is splitted to allow accrueAccountInternal to be called from other functions\n     **/\n    function accrueAccount(address account) override external {\n        accrueAccountInternal(account);\n    }\n\n    /**\n     * @dev Note: Does not accrue interest first\n     * @param utilization The utilization to check the supply rate for\n     * @return The per second supply rate at `utilization`\n     */\n    function getSupplyRate(uint utilization) override public view returns (uint64) {\n        /// No supply - no supply interest\n        if (totalSupplyBase == 0) return 0;\n\n        /// In several situations new market with reserves and have lenders, but may not have borrows\n        /// In such case, lenders will farm on this market on the base supply per second, until reserves are exhausted\n        /// So, we limit the farming possibility by the size of reserves:\n        /// - for the new market with no borrows, the balance consists of reserves and supplied base asset\n        /// - totalSupply() will grow based on the base rate until it will reach the available balance\n        /// - once it happens - we cut off the supply rate to avoid illiquidity (when lenders will not be able to\n        ///   withdraw as there is no tokens on the Comet balance\n        if (utilization == 0 && supplyPerSecondInterestRateBase != 0) {\n            if (presentValueSupply(baseSupplyIndex, totalSupplyBase) >= IERC20NonStandard(baseToken).balanceOf(address(this))) return 0;\n        }\n\n        if (utilization <= supplyKink) {\n            // interestRateBase + interestRateSlopeLow * utilization\n            return safe64(supplyPerSecondInterestRateBase + mulFactor(supplyPerSecondInterestRateSlopeLow, utilization));\n        } else {\n            // interestRateBase + interestRateSlopeLow * kink + interestRateSlopeHigh * (utilization - kink)\n            return safe64(supplyPerSecondInterestRateBase + mulFactor(supplyPerSecondInterestRateSlopeLow, supplyKink) + mulFactor(supplyPerSecondInterestRateSlopeHigh, (utilization - supplyKink)));\n        }\n    }\n\n    /**\n     * @dev Note: Does not accrue interest first\n     * @param utilization The utilization to check the borrow rate for\n     * @return The per second borrow rate at `utilization`\n     */\n    function getBorrowRate(uint utilization) override public view returns (uint64) {\n         /// No borrow - no borrow interest\n        if (totalBorrowBase == 0) return 0;\n\n        if (utilization <= borrowKink) {\n            // interestRateBase + interestRateSlopeLow * utilization\n            return safe64(borrowPerSecondInterestRateBase + mulFactor(borrowPerSecondInterestRateSlopeLow, utilization));\n        } else {\n            // interestRateBase + interestRateSlopeLow * kink + interestRateSlopeHigh * (utilization - kink)\n            return safe64(borrowPerSecondInterestRateBase + mulFactor(borrowPerSecondInterestRateSlopeLow, borrowKink) + mulFactor(borrowPerSecondInterestRateSlopeHigh, (utilization - borrowKink)));\n        }\n    }\n\n    /**\n     * @dev Note: Does not accrue interest first\n     * @return The utilization rate of the base asset\n     */\n    function getUtilization() override public view returns (uint) {\n        uint totalSupply_ = presentValueSupply(baseSupplyIndex, totalSupplyBase);\n        uint totalBorrow_ = presentValueBorrow(baseBorrowIndex, totalBorrowBase);\n        if (totalSupply_ == 0) {\n            return 0;\n        } else {\n            return totalBorrow_ * FACTOR_SCALE / totalSupply_;\n        }\n    }\n\n    /**\n     * @notice Get the current price from a feed\n     * @param priceFeed The address of a price feed\n     * @return The price, scaled by `PRICE_SCALE`\n     */\n    function getPrice(address priceFeed) override public view returns (uint256) {\n        (, int price, , , ) = IPriceFeed(priceFeed).latestRoundData();\n        if (price <= 0) revert BadPrice();\n        return uint256(price);\n    }\n\n    /**\n     * @notice Gets the total balance of protocol collateral reserves for an asset\n     * @dev Note: Reverts if collateral reserves are somehow negative, which should not be possible\n     * @param asset The collateral asset\n     */\n    function getCollateralReserves(address asset) override public view returns (uint) {\n        return IERC20NonStandard(asset).balanceOf(address(this)) - totalsCollateral[asset].totalSupplyAsset;\n    }\n\n    /**\n     * @notice Gets the total amount of protocol reserves of the base asset\n     */\n    function getReserves() override public view returns (int) {\n        (uint64 baseSupplyIndex_, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime);\n        uint balance = IERC20NonStandard(baseToken).balanceOf(address(this));\n        uint totalSupply_ = presentValueSupply(baseSupplyIndex_, totalSupplyBase);\n        uint totalBorrow_ = presentValueBorrow(baseBorrowIndex_, totalBorrowBase);\n        return signed256(balance) - signed256(totalSupply_) + signed256(totalBorrow_);\n    }\n\n    /**\n     * @notice Check whether an account has enough collateral to borrow\n     * @param account The address to check\n     * @return Whether the account is minimally collateralized enough to borrow\n     */\n    function isBorrowCollateralized(address account) override public view returns (bool) {\n        int104 principal = userBasic[account].principal;\n\n        if (principal >= 0) {\n            return true;\n        }\n\n        uint16 assetsIn = userBasic[account].assetsIn;\n        uint8 _reserved = userBasic[account]._reserved;\n        int liquidity = signedMulPrice(\n            presentValue(principal),\n            getPrice(baseTokenPriceFeed),\n            uint64(baseScale)\n        );\n\n        AssetInfo memory asset;\n        uint256 newAmount;\n        for (uint8 i; i < numAssets; ++i) {\n            if (isInAsset(assetsIn, i, _reserved)) {\n                if (liquidity >= 0) {\n                    return true;\n                }\n\n                asset = getAssetInfo(i);\n\n                // Block ALL borrow-side actions when the borrower still holds deactivated collateral.\n                // This revert is intentionally broad: it prevents borrowing, withdrawing other\n                // collateral, and transferring — even if the remaining active collateral would\n                // pass the collateralization check on its own. The purpose is to force the\n                // borrower to withdraw the deactivated collateral FIRST before doing anything\n                // else (see the deactivation lifecycle comment on isCollateralDeactivated).\n                //\n                // If the borrower cannot withdraw the deactivated collateral without becoming\n                // under-collateralized, they are stuck and must wait for liquidation.\n                if (isCollateralDeactivated(asset.offset)) revert TokenIsDeactivated(asset.asset);\n\n                // Mechanism to skip assets with no borrowing power. It avoids getPrice() call price feed,\n                // so in case if excluded asset's oracle reverts (e.g. stale, broken, decommissioned),\n                // it won't block the entire collateralization check, and won't paralyze borrows and transfers.\n                // the asset has zero influence on their borrow capacity.\n                if (asset.borrowCollateralFactor == 0) { \n                    continue; \n                }\n\n                newAmount = mulPrice(\n                    userCollateral[account][asset.asset].balance,\n                    getPrice(asset.priceFeed),\n                    asset.scale\n                );\n                liquidity += signed256(mulFactor(\n                    newAmount,\n                    asset.borrowCollateralFactor\n                ));\n            }\n        }\n\n        return liquidity >= 0;\n    }\n\n    /**\n     * @notice Check whether an account has enough collateral to not be liquidated\n     * @param account The address to check\n     * @return Whether the account is minimally collateralized enough to not be liquidated\n     *\n     * @dev Intentionally does NOT check isCollateralDeactivated. Unlike isBorrowCollateralized,\n     *      which reverts on deactivated collateral to block borrower actions, this function\n     *      must always return a result so that liquidation remains possible. A stuck borrower\n     *      who cannot withdraw deactivated collateral (see withdrawCollateral) relies on\n     *      liquidation as their only exit path. If isLiquidatable reverted on deactivated\n     *      collateral, the borrower would be permanently frozen with no way out.\n     *\n     *      When liquidateCollateralFactor is 0 for the deactivated asset, it contributes\n     *      nothing to the liquidity calculation, making the account easier to liquidate.\n     */\n    function isLiquidatable(address account) override public view returns (bool) {\n        (bool liquidatable, ,) = isLiquidatableInternal(account);\n        return liquidatable;\n    }\n\n    function isLiquidatableInternal(address account) internal view returns (\n        bool liquidatable,\n        uint256 basePrice,\n        uint256[] memory assetPrices\n    ) {\n        int104 principal = userBasic[account].principal;\n\n        if (principal >= 0) return (false, basePrice, assetPrices);\n\n        assetPrices = new uint256[](numAssets);\n        uint16 assetsIn = userBasic[account].assetsIn;\n        uint8 _reserved = userBasic[account]._reserved;\n        basePrice = getPrice(baseTokenPriceFeed);\n        int liquidity = signedMulPrice(\n            presentValue(principal),\n            basePrice,\n            uint64(baseScale)\n        );\n\n        AssetInfo memory asset;\n        uint256 newAmount;\n        for (uint8 i; i < numAssets; ++i) {\n            if (isInAsset(assetsIn, i, _reserved)) {\n                if (liquidity >= 0) return (false, basePrice, assetPrices);\n\n                asset = getAssetInfo(i);\n\n                // Skip assets that do not count toward the liquidation threshold. It avoids getPrice() call for price feed\n                // so in case if excluded asset's oracle reverts (e.g. stale, broken, decommissioned),\n                // it won't block the entire liquidation check, and won't paralyze liquidations of accounts which hold it.\n                if (asset.liquidateCollateralFactor == 0) { \n                    continue; \n                }\n\n                assetPrices[i] = getPrice(asset.priceFeed);\n\n                newAmount = mulPrice(\n                    userCollateral[account][asset.asset].balance,\n                    assetPrices[i],\n                    asset.scale\n                );\n                liquidity += signed256(mulFactor(newAmount, asset.liquidateCollateralFactor));\n            }\n        }\n\n        return (liquidity < 0, basePrice, assetPrices);\n    }\n\n    /**\n     * @dev The change in principal broken into repay and supply amounts\n     */\n    function repayAndSupplyAmount(int104 oldPrincipal, int104 newPrincipal) internal pure returns (uint104, uint104) {\n        // If the new principal is less than the old principal, then no amount has been repaid or supplied\n        if (newPrincipal < oldPrincipal) return (0, 0);\n\n        if (newPrincipal <= 0) {\n            return (uint104(newPrincipal - oldPrincipal), 0);\n        } else if (oldPrincipal >= 0) {\n            return (0, uint104(newPrincipal - oldPrincipal));\n        } else {\n            return (uint104(-oldPrincipal), uint104(newPrincipal));\n        }\n    }\n\n    /**\n     * @dev The change in principal broken into withdraw and borrow amounts\n     */\n    function withdrawAndBorrowAmount(int104 oldPrincipal, int104 newPrincipal) internal pure returns (uint104, uint104) {\n        // If the new principal is greater than the old principal, then no amount has been withdrawn or borrowed\n        if (newPrincipal > oldPrincipal) return (0, 0);\n\n        if (newPrincipal >= 0) {\n            return (uint104(oldPrincipal - newPrincipal), 0);\n        } else if (oldPrincipal <= 0) {\n            return (0, uint104(oldPrincipal - newPrincipal));\n        } else {\n            return (uint104(oldPrincipal), uint104(-newPrincipal));\n        }\n    }\n\n    /**\n     * @notice Pauses different actions within Comet\n     * @param supplyPaused Boolean for pausing supply actions\n     * @param transferPaused Boolean for pausing transfer actions\n     * @param withdrawPaused Boolean for pausing withdraw actions\n     * @param absorbPaused Boolean for pausing absorb actions\n     * @param buyPaused Boolean for pausing buy actions\n     */\n    function pause(\n        bool supplyPaused,\n        bool transferPaused,\n        bool withdrawPaused,\n        bool absorbPaused,\n        bool buyPaused\n    ) override external {\n        if (msg.sender != governor && msg.sender != pauseGuardian) revert Unauthorized();\n\n        pauseFlags =\n            uint8(0) |\n            (toUInt8(supplyPaused) << PAUSE_SUPPLY_OFFSET) |\n            (toUInt8(transferPaused) << PAUSE_TRANSFER_OFFSET) |\n            (toUInt8(withdrawPaused) << PAUSE_WITHDRAW_OFFSET) |\n            (toUInt8(absorbPaused) << PAUSE_ABSORB_OFFSET) |\n            (toUInt8(buyPaused) << PAUSE_BUY_OFFSET);\n\n        emit PauseAction(supplyPaused, transferPaused, withdrawPaused, absorbPaused, buyPaused);\n    }\n\n    /**\n     * @return Whether or not supply actions are paused\n     */\n    function isSupplyPaused() override public view returns (bool) {\n        return toBool(pauseFlags & (uint8(1) << PAUSE_SUPPLY_OFFSET));\n    }\n\n    /**\n     * @return Whether or not transfer actions are paused\n     */\n    function isTransferPaused() override public view returns (bool) {\n        return toBool(pauseFlags & (uint8(1) << PAUSE_TRANSFER_OFFSET));\n    }\n\n    /**\n     * @return Whether or not withdraw actions are paused\n     */\n    function isWithdrawPaused() override public view returns (bool) {\n        return toBool(pauseFlags & (uint8(1) << PAUSE_WITHDRAW_OFFSET));\n    }\n\n    /**\n     * @return Whether or not absorb actions are paused\n     */\n    function isAbsorbPaused() override public view returns (bool) {\n        return toBool(pauseFlags & (uint8(1) << PAUSE_ABSORB_OFFSET));\n    }\n\n    /**\n     * @return Whether or not buy actions are paused\n     */\n    function isBuyPaused() override public view returns (bool) {\n        return toBool(pauseFlags & (uint8(1) << PAUSE_BUY_OFFSET));\n    }\n\n    /**\n     * @return Whether or not lenders withdraw actions are paused\n     */\n    function isLendersWithdrawPaused() public view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << PAUSE_LENDERS_WITHDRAW_OFFSET)) != 0;\n    }\n\n    /**\n     * @return Whether or not borrowers withdraw actions are paused\n     */\n    function isBorrowersWithdrawPaused() public view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << PAUSE_BORROWERS_WITHDRAW_OFFSET)) != 0;\n    }\n\n    /**\n     * @param assetIndex The index of the asset (offset)\n     * @return Whether or not collateral asset withdraw actions are paused\n     */\n    function isCollateralAssetWithdrawPaused(uint24 assetIndex)  public view returns (bool) {\n        return (collateralsWithdrawPauseFlags & (uint24(1) << assetIndex)) != 0;\n    }\n\n    /**\n     * @return Whether or not collateral withdraw actions are paused\n     */\n    function isCollateralWithdrawPaused() public view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << PAUSE_COLLATERALS_WITHDRAW_OFFSET)) != 0;\n    }\n\n    /**\n     * @return Whether or not collateral supply actions are paused\n     */\n    function isCollateralSupplyPaused() public view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << PAUSE_COLLATERAL_SUPPLY_OFFSET)) != 0;\n    }\n\n    /**\n     * @return Whether or not base supply actions are paused\n     */\n    function isBaseSupplyPaused() public view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << PAUSE_BASE_SUPPLY_OFFSET)) != 0;\n    }\n\n    /**\n     * @param assetIndex The index of the asset (offset)\n     * @return Whether or not collateral asset supply actions are paused\n     */\n    function isCollateralAssetSupplyPaused(uint24 assetIndex) public view returns (bool) {\n        return (collateralsSupplyPauseFlags & (uint24(1) << assetIndex)) != 0;\n    }\n\n    /**\n     * @return Whether or not lenders transfer actions are paused\n     */\n    function isLendersTransferPaused() public view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << PAUSE_LENDERS_TRANSFER_OFFSET)) != 0;\n    }\n\n    /**\n     * @return Whether or not borrowers transfer actions are paused\n     */\n    function isBorrowersTransferPaused() public view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << PAUSE_BORROWERS_TRANSFER_OFFSET)) != 0;\n    }\n\n    /**\n     * @param assetIndex The index of the asset (offset)\n     * @return Whether or not collateral asset transfer actions are paused\n     */\n    function isCollateralAssetTransferPaused(uint24 assetIndex) public view returns (bool) {\n        return (collateralsTransferPauseFlags & (uint24(1) << assetIndex)) != 0;\n    }\n\n    /**\n     * @return Whether or not collateral transfer actions are paused\n     */\n    function isCollateralTransferPaused() public view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << PAUSE_COLLATERALS_TRANSFER_OFFSET)) != 0;\n    }\n\n    /**\n     * @notice Check if a collateral asset is deactivated\n     * @param assetIndex The index of the asset\n     * @return Whether the collateral asset is deactivated\n     *\n     * Deactivation is an emergency action only. It can be called and executed\n     * immediately by the pause guardian via `deactivateCollateral`.\n     * When executed, the asset's bit is set in `deactivatedCollaterals`, and\n     * supply and transfer for that collateral are paused.\n     *\n     * ─── Impact on borrowers holding deactivated collateral ─────────────────────\n     *\n     * If a borrower still has debt and still holds deactivated collateral, borrow-side\n     * actions are blocked because `isBorrowCollateralized` reverts with\n     * `TokenIsDeactivated` when that asset is encountered in `assetsIn`.\n     *\n     * The borrower then has two options:\n     *\n     *   1. Repay debt until principal is > 0 (i.e. no borrow position). This avoids\n     *      collateral liquidity checks in `isBorrowCollateralized`, allowing the borrower\n     *      to withdraw the deactivated collateral.\n     *\n     *   2. Wait for liquidation (`absorbInternal`), where collateral is seized and debt\n     *      is absorbed according to the protocol's liquidation rules.\n     *\n     * If a user is not a borrower (no debt / principal >= 0), they can withdraw\n     * deactivated collateral without these borrow-side restrictions.\n     */\n    function isCollateralDeactivated(uint24 assetIndex) public view returns (bool) {\n        return (deactivatedCollaterals & (uint24(1) << assetIndex)) != 0;\n    }\n\n    /**\n     * @dev Multiply a number by a factor\n     */\n    function mulFactor(uint n, uint factor) internal pure returns (uint) {\n        return n * factor / FACTOR_SCALE;\n    }\n\n    /**\n     * @dev Divide a number by an amount of base\n     */\n    function divBaseWei(uint n, uint baseWei) internal view returns (uint) {\n        return n * baseScale / baseWei;\n    }\n\n    /**\n     * @dev Multiply a `fromScale` quantity by a price, returning a common price quantity\n     */\n    function mulPrice(uint n, uint price, uint64 fromScale) internal pure returns (uint) {\n        return n * price / fromScale;\n    }\n\n    /**\n     * @dev Multiply a signed `fromScale` quantity by a price, returning a common price quantity\n     */\n    function signedMulPrice(int n, uint price, uint64 fromScale) internal pure returns (int) {\n        return n * signed256(price) / int256(uint256(fromScale));\n    }\n\n    /**\n     * @dev Divide a common price quantity by a price, returning a `toScale` quantity\n     */\n    function divPrice(uint n, uint price, uint64 toScale) internal pure returns (uint) {\n        return n * toScale / price;\n    }\n\n    /**\n     * @dev Whether user has a non-zero balance of an asset, given assetsIn flags\n     * @dev _reserved is used to check bits 16-23 of assetsIn\n     */\n    function isInAsset(uint16 assetsIn, uint8 assetOffset, uint8 _reserved) internal pure returns (bool) {\n        if (assetOffset < 16) {\n            // check bit in assetsIn (for bits 0-15)\n            return (assetsIn & (uint16(1) << assetOffset)) != 0;\n        } else if (assetOffset < 24) {\n            // check bit in reserved (for bits 16-23)\n            return (_reserved & (uint8(1) << (assetOffset - 16))) != 0;\n        }\n        return false; // if assetOffset >= 24 (should not happen)\n    }\n\n    /**\n     * @dev Update assetsIn bit vector if user has entered or exited an asset\n     */\n    function updateAssetsIn(\n        address account,\n        AssetInfo memory assetInfo,\n        uint128 initialUserBalance,\n        uint128 finalUserBalance\n    ) internal {\n        if (initialUserBalance == 0 && finalUserBalance != 0) {\n            // set bit for asset\n            if (assetInfo.offset < 16) {\n                // set bit in assetsIn for bits 0-15\n                userBasic[account].assetsIn |= (uint16(1) << assetInfo.offset);\n            } else if (assetInfo.offset < 24) {\n                // set bit in _reserved for bits 16-23\n                userBasic[account]._reserved |= (uint8(1) << (assetInfo.offset - 16));\n            }\n        } else if (initialUserBalance != 0 && finalUserBalance == 0) {\n            // clear bit for asset\n            if (assetInfo.offset < 16) {\n                // clear bit in assetsIn for bits 0-15\n                userBasic[account].assetsIn &= ~(uint16(1) << assetInfo.offset);\n            } else if (assetInfo.offset < 24) {\n                // clear bit in _reserved for bits 16-23\n                userBasic[account]._reserved &= ~(uint8(1) << (assetInfo.offset - 16));\n            }\n        }\n    }\n\n    /**\n     * @dev Write updated principal to store and tracking participation\n     */\n    function updateBasePrincipal(address account, UserBasic memory basic, int104 principalNew) internal {\n        int104 principal = basic.principal;\n        basic.principal = principalNew;\n\n        if (principal >= 0) {\n            uint indexDelta = uint256(trackingSupplyIndex - basic.baseTrackingIndex);\n            basic.baseTrackingAccrued += safe64(uint104(principal) * indexDelta / trackingIndexScale / accrualDescaleFactor);\n        } else {\n            uint indexDelta = uint256(trackingBorrowIndex - basic.baseTrackingIndex);\n            basic.baseTrackingAccrued += safe64(uint104(-principal) * indexDelta / trackingIndexScale / accrualDescaleFactor);\n        }\n\n        if (principalNew >= 0) {\n            basic.baseTrackingIndex = trackingSupplyIndex;\n        } else {\n            basic.baseTrackingIndex = trackingBorrowIndex;\n        }\n\n        userBasic[account] = basic;\n    }\n\n    /**\n     * @dev Safe ERC20 transfer in and returns the final amount transferred (taking into account any fees)\n     * @dev Note: Safely handles non-standard ERC-20 tokens that do not return a value. See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n     */\n    function doTransferIn(address asset, address from, uint amount) internal returns (uint) {\n        uint256 preTransferBalance = IERC20NonStandard(asset).balanceOf(address(this));\n        IERC20NonStandard(asset).transferFrom(from, address(this), amount);\n        bool success;\n        assembly (\"memory-safe\") {\n            switch returndatasize()\n                case 0 {                       // This is a non-standard ERC-20\n                    success := not(0)          // set success to true\n                }\n                case 32 {                      // This is a compliant ERC-20\n                    returndatacopy(0, 0, 32)\n                    success := mload(0)        // Set `success = returndata` of override external call\n                }\n                default {                      // This is an excessively non-compliant ERC-20, revert.\n                    revert(0, 0)\n                }\n        }\n        if (!success) revert TransferInFailed();\n        return IERC20NonStandard(asset).balanceOf(address(this)) - preTransferBalance;\n    }\n\n    /**\n     * @dev Safe ERC20 transfer out\n     * @dev Note: Safely handles non-standard ERC-20 tokens that do not return a value. See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n     */\n    function doTransferOut(address asset, address to, uint amount) internal {\n        IERC20NonStandard(asset).transfer(to, amount);\n        bool success;\n        assembly (\"memory-safe\") {\n            switch returndatasize()\n                case 0 {                       // This is a non-standard ERC-20\n                    success := not(0)          // set success to true\n                }\n                case 32 {                      // This is a compliant ERC-20\n                    returndatacopy(0, 0, 32)\n                    success := mload(0)        // Set `success = returndata` of override external call\n                }\n                default {                      // This is an excessively non-compliant ERC-20, revert.\n                    revert(0, 0)\n                }\n        }\n        if (!success) revert TransferOutFailed();\n    }\n\n    /**\n     * @notice Supply an amount of asset to the protocol\n     * @param asset The asset to supply\n     * @param amount The quantity to supply\n     */\n    function supply(address asset, uint amount) override external {\n        return supplyInternal(msg.sender, msg.sender, asset, amount);\n    }\n\n    /**\n     * @notice Supply an amount of asset to dst\n     * @param dst The address which will hold the balance\n     * @param asset The asset to supply\n     * @param amount The quantity to supply\n     */\n    function supplyTo(address dst, address asset, uint amount) override external {\n        return supplyInternal(msg.sender, dst, asset, amount);\n    }\n\n    /**\n     * @notice Supply an amount of asset from `from` to dst, if allowed\n     * @param from The supplier address\n     * @param dst The address which will hold the balance\n     * @param asset The asset to supply\n     * @param amount The quantity to supply\n     */\n    function supplyFrom(address from, address dst, address asset, uint amount) override external {\n        return supplyInternal(from, dst, asset, amount);\n    }\n\n    /**\n     * @dev Supply either collateral or base asset, depending on the asset, if operator is allowed\n     * @dev Note: Specifying an `amount` of uint256.max will repay all of `dst`'s accrued base borrow balance\n     */\n    function supplyInternal(address from, address dst, address asset, uint amount) internal nonReentrant {\n        if (isSupplyPaused()) revert Paused();\n        if (!hasPermission(from, msg.sender)) revert Unauthorized();\n\n        if (asset == baseToken) {\n            if (isBaseSupplyPaused()) revert BaseSupplyPaused();\n            if (amount == type(uint256).max) {\n                amount = borrowBalanceOf(dst);\n            }\n            return supplyBase(from, dst, amount);\n        } else {\n            if (isCollateralSupplyPaused()) revert CollateralSupplyPaused();\n            return supplyCollateral(from, dst, asset, safe128(amount));\n        }\n    }\n\n    /**\n     * @dev Supply an amount of base asset from `from` to dst\n     */\n    function supplyBase(address from, address dst, uint256 amount) internal {\n        amount = doTransferIn(baseToken, from, amount);\n        accrueInternal();\n\n        UserBasic memory dstUser = userBasic[dst];\n        int104 dstPrincipal = dstUser.principal;\n        int256 dstBalance = presentValue(dstPrincipal) + signed256(amount);\n        int104 dstPrincipalNew = principalValue(dstBalance);\n\n        (uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(dstPrincipal, dstPrincipalNew);\n\n        totalSupplyBase += supplyAmount;\n        totalBorrowBase -= repayAmount;\n\n        updateBasePrincipal(dst, dstUser, dstPrincipalNew);\n\n        emit Supply(from, dst, amount);\n\n        if (supplyAmount > 0) {\n            emit Transfer(address(0), dst, presentValueSupply(baseSupplyIndex, supplyAmount));\n        }\n    }\n\n    /**\n     * @dev Supply an amount of collateral asset from `from` to dst\n     */\n    function supplyCollateral(address from, address dst, address asset, uint128 amount) internal {\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\n        uint8 offset = assetInfo.offset;\n\n        if (isCollateralAssetSupplyPaused(offset)) revert CollateralAssetSupplyPaused(offset);\n        accrueAccountInternal(dst);\n\n        amount = safe128(doTransferIn(asset, from, amount));\n\n        TotalsCollateral memory totals = totalsCollateral[asset];\n        totals.totalSupplyAsset += amount;\n        if (totals.totalSupplyAsset > assetInfo.supplyCap) revert SupplyCapExceeded();\n\n        uint128 dstCollateral = userCollateral[dst][asset].balance;\n        uint128 dstCollateralNew = dstCollateral + amount;\n\n        totalsCollateral[asset] = totals;\n        userCollateral[dst][asset].balance = dstCollateralNew;\n\n        updateAssetsIn(dst, assetInfo, dstCollateral, dstCollateralNew);\n\n        emit SupplyCollateral(from, dst, asset, amount);\n    }\n\n    /**\n     * @notice ERC20 transfer an amount of base token to dst\n     * @param dst The recipient address\n     * @param amount The quantity to transfer\n     * @return true\n     */\n    function transfer(address dst, uint amount) override external returns (bool) {\n        transferInternal(msg.sender, msg.sender, dst, baseToken, amount);\n        return true;\n    }\n\n    /**\n     * @notice ERC20 transfer an amount of base token from src to dst, if allowed\n     * @param src The sender address\n     * @param dst The recipient address\n     * @param amount The quantity to transfer\n     * @return true\n     */\n    function transferFrom(address src, address dst, uint amount) override external returns (bool) {\n        transferInternal(msg.sender, src, dst, baseToken, amount);\n        return true;\n    }\n\n    /**\n     * @notice Transfer an amount of asset to dst\n     * @param dst The recipient address\n     * @param asset The asset to transfer\n     * @param amount The quantity to transfer\n     */\n    function transferAsset(address dst, address asset, uint amount) override external {\n        return transferInternal(msg.sender, msg.sender, dst, asset, amount);\n    }\n\n    /**\n     * @notice Transfer an amount of asset from src to dst, if allowed\n     * @param src The sender address\n     * @param dst The recipient address\n     * @param asset The asset to transfer\n     * @param amount The quantity to transfer\n     */\n    function transferAssetFrom(address src, address dst, address asset, uint amount) override external {\n        return transferInternal(msg.sender, src, dst, asset, amount);\n    }\n\n    /**\n     * @dev Transfer either collateral or base asset, depending on the asset, if operator is allowed\n     * @dev Note: Specifying an `amount` of uint256.max will transfer all of `src`'s accrued base balance\n     */\n    function transferInternal(address operator, address src, address dst, address asset, uint amount) internal nonReentrant {\n        if (isTransferPaused()) revert Paused();\n        if (!hasPermission(src, operator)) revert Unauthorized();\n        if (src == dst) revert NoSelfTransfer();\n\n        if (asset == baseToken) {\n            if (amount == type(uint256).max) {\n                amount = balanceOf(src);\n            }\n            return transferBase(src, dst, amount);\n        } else {\n            if (isCollateralTransferPaused()) revert CollateralTransferPaused();\n            return transferCollateral(src, dst, asset, safe128(amount));\n        }\n    }\n\n    /**\n     * @dev Transfer an amount of base asset from src to dst, borrowing if possible/necessary\n     */\n    function transferBase(address src, address dst, uint256 amount) internal {\n        accrueInternal();\n\n        UserBasic memory srcUser = userBasic[src];\n        UserBasic memory dstUser = userBasic[dst];\n\n        int104 srcPrincipal = srcUser.principal;\n        int104 dstPrincipal = dstUser.principal;\n        int256 srcBalance = presentValue(srcPrincipal) - signed256(amount);\n        int256 dstBalance = presentValue(dstPrincipal) + signed256(amount);\n        int104 srcPrincipalNew = principalValue(srcBalance);\n        int104 dstPrincipalNew = principalValue(dstBalance);\n\n        (uint104 withdrawAmount, uint104 borrowAmount) = withdrawAndBorrowAmount(srcPrincipal, srcPrincipalNew);\n        (uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(dstPrincipal, dstPrincipalNew);\n\n        // Note: Instead of `total += addAmount - subAmount` to avoid underflow errors.\n        totalSupplyBase = totalSupplyBase + supplyAmount - withdrawAmount;\n        totalBorrowBase = totalBorrowBase + borrowAmount - repayAmount;\n\n        updateBasePrincipal(src, srcUser, srcPrincipalNew);\n        updateBasePrincipal(dst, dstUser, dstPrincipalNew);\n\n        if (srcBalance < 0) {\n            if (isBorrowersTransferPaused()) revert BorrowersTransferPaused();\n            if (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall();\n            if (!isBorrowCollateralized(src)) revert NotCollateralized();\n\n            /// @dev Guard against utilization being pushed above the supported ceiling via a borrow-side transferBase.\n            /// When the source account is in a borrow position, the supply credited to the destination is new\n            /// liquidity that the destination can immediately withdraw. To capture this worst case, utilization is\n            /// evaluated against total supply *excluding* the destination's newly credited amount — i.e. the supply\n            /// that would remain if the destination withdrew right away. This prevents a pattern where a borrower\n            /// transfers base to a fresh account that then withdraws, draining pool liquidity and pushing\n            /// utilization beyond MAX_SUPPORTED_UTILIZATION.\n            uint256 totalSupplyWithoutDst = presentValueSupply(baseSupplyIndex, totalSupplyBase - supplyAmount);\n            uint256 presentTotalBorrow = presentValueBorrow(baseBorrowIndex, totalBorrowBase);\n            if (totalSupplyWithoutDst > 0 && presentTotalBorrow * FACTOR_SCALE / totalSupplyWithoutDst > MAX_SUPPORTED_UTILIZATION) revert ExceedsSupportedUtilization();\n        } else {\n            if (isLendersTransferPaused()) revert LendersTransferPaused();\n        }\n\n        if (withdrawAmount > 0) {\n            emit Transfer(src, address(0), presentValueSupply(baseSupplyIndex, withdrawAmount));\n        }\n\n        if (supplyAmount > 0) {\n            emit Transfer(address(0), dst, presentValueSupply(baseSupplyIndex, supplyAmount));\n        }\n    }\n\n    /**\n     * @dev Transfer an amount of collateral asset from src to dst\n     */\n    function transferCollateral(address src, address dst, address asset, uint128 amount) internal {\n        uint128 srcCollateral = userCollateral[src][asset].balance;\n        uint128 dstCollateral = userCollateral[dst][asset].balance;\n        uint128 srcCollateralNew = srcCollateral - amount;\n        uint128 dstCollateralNew = dstCollateral + amount;\n\n        userCollateral[src][asset].balance = srcCollateralNew;\n        userCollateral[dst][asset].balance = dstCollateralNew;\n\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\n        uint8 offset = assetInfo.offset;\n\n        if (isCollateralAssetTransferPaused(offset)) revert CollateralAssetTransferPaused(offset);\n        accrueAccountInternal(src);\n        accrueAccountInternal(dst);\n        updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew);\n        updateAssetsIn(dst, assetInfo, dstCollateral, dstCollateralNew);\n\n        if (!isBorrowCollateralized(src)) revert NotCollateralized();\n\n        emit TransferCollateral(src, dst, asset, amount);\n    }\n\n    /**\n     * @notice Withdraw an amount of asset from the protocol\n     * @param asset The asset to withdraw\n     * @param amount The quantity to withdraw\n     */\n    function withdraw(address asset, uint amount) override external {\n        return withdrawInternal(msg.sender, msg.sender, msg.sender, asset, amount);\n    }\n\n    /**\n     * @notice Withdraw an amount of asset to `to`\n     * @param to The recipient address\n     * @param asset The asset to withdraw\n     * @param amount The quantity to withdraw\n     */\n    function withdrawTo(address to, address asset, uint amount) override external {\n        return withdrawInternal(msg.sender, msg.sender, to, asset, amount);\n    }\n\n    /**\n     * @notice Withdraw an amount of asset from src to `to`, if allowed\n     * @param src The sender address\n     * @param to The recipient address\n     * @param asset The asset to withdraw\n     * @param amount The quantity to withdraw\n     */\n    function withdrawFrom(address src, address to, address asset, uint amount) override external {\n        return withdrawInternal(msg.sender, src, to, asset, amount);\n    }\n\n    /**\n     * @dev Withdraw either collateral or base asset, depending on the asset, if operator is allowed\n     * @dev Note: Specifying an `amount` of uint256.max will withdraw all of `src`'s accrued base balance\n     */\n    function withdrawInternal(address operator, address src, address to, address asset, uint amount) internal nonReentrant {\n        if (isWithdrawPaused()) revert Paused();\n        if (!hasPermission(src, operator)) revert Unauthorized();\n\n        if (asset == baseToken) {\n            if (amount == type(uint256).max) {\n                amount = balanceOf(src);\n            }\n            return withdrawBase(src, to, amount);\n        } else {\n            if (isCollateralWithdrawPaused()) revert CollateralWithdrawPaused();\n            return withdrawCollateral(src, to, asset, safe128(amount));\n        }\n    }\n\n    /**\n     * @dev Withdraw an amount of base asset from src to `to`, borrowing if possible/necessary\n     */\n    function withdrawBase(address src, address to, uint256 amount) internal {\n        accrueInternal();\n\n        UserBasic memory srcUser = userBasic[src];\n        int104 srcPrincipal = srcUser.principal;\n        int256 srcBalance = presentValue(srcPrincipal) - signed256(amount);\n        int104 srcPrincipalNew = principalValue(srcBalance);\n\n        (uint104 withdrawAmount, uint104 borrowAmount) = withdrawAndBorrowAmount(srcPrincipal, srcPrincipalNew);\n\n        totalSupplyBase -= withdrawAmount;\n        totalBorrowBase += borrowAmount;\n\n        updateBasePrincipal(src, srcUser, srcPrincipalNew);\n\n        if (srcBalance < 0) {\n            if (isBorrowersWithdrawPaused()) revert BorrowersWithdrawPaused();\n            if (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall();\n            if (!isBorrowCollateralized(src)) revert NotCollateralized();\n            /// @dev safeguard against the over-utilization leading to illiquidity and reserves exhaustion\n            /// At this point totals are updated and it is a borrow case, so we can check resulting utilization\n            if (getUtilization() > MAX_SUPPORTED_UTILIZATION) revert ExceedsSupportedUtilization();\n        } else {\n            if (isLendersWithdrawPaused()) revert LendersWithdrawPaused();\n        }\n\n        doTransferOut(baseToken, to, amount);\n\n        emit Withdraw(src, to, amount);\n\n        if (withdrawAmount > 0) {\n            emit Transfer(src, address(0), presentValueSupply(baseSupplyIndex, withdrawAmount));\n        }\n    }\n\n    /**\n     * @dev Withdraw an amount of collateral asset from src to `to`\n     *\n     * Note on deactivated collateral:\n     *   This is the path a borrower must use to remove deactivated collateral from their\n     *   account before they can resume normal operations (see deactivation lifecycle on\n     *   isCollateralDeactivated). If the borrower withdraws ALL of the deactivated asset,\n     *   updateAssetsIn clears its bit from `assetsIn`, so the subsequent\n     *   isBorrowCollateralized call no longer encounters the deactivated asset.\n     *\n     *   However, if removing the deactivated collateral leaves the borrower under-\n     *   collateralized (remaining active collateral is insufficient for the borrow),\n     *   isBorrowCollateralized reverts with NotCollateralized — the borrower is stuck.\n     *   In this case the borrower has no choice but to wait for liquidation, which will\n     *   seize all collateral (including deactivated) and absorb the debt.\n     */\n    function withdrawCollateral(address src, address to, address asset, uint128 amount) internal {\n        accrueAccountInternal(src);\n        \n        uint128 srcCollateral = userCollateral[src][asset].balance;\n        uint128 srcCollateralNew = srcCollateral - amount;\n\n        totalsCollateral[asset].totalSupplyAsset -= amount;\n        userCollateral[src][asset].balance = srcCollateralNew;\n\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\n        uint8 offset = assetInfo.offset;\n        if (isCollateralAssetWithdrawPaused(offset)) revert CollateralAssetWithdrawPaused(offset);\n\n        updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew);\n\n        if (!isBorrowCollateralized(src)) revert NotCollateralized();\n\n        doTransferOut(asset, to, amount);\n\n        emit WithdrawCollateral(src, to, asset, amount);\n    }\n\n    /**\n     * @notice Absorb a list of underwater accounts onto the protocol balance sheet\n     * @param absorber The recipient of the incentive paid to the caller of absorb\n     * @param accounts The list of underwater accounts to absorb\n     */\n    function absorb(address absorber, address[] calldata accounts) override external {\n        if (isAbsorbPaused()) revert Paused();\n\n        uint startGas = gasleft();\n        accrueInternal();\n        for (uint i = 0; i < accounts.length; ) {\n            absorbInternal(absorber, accounts[i]);\n            unchecked { i++; }\n        }\n        uint gasUsed = startGas - gasleft();\n\n        // Note: liquidator points are an imperfect tool for governance,\n        //  to be used while evaluating strategies for incentivizing absorption.\n        // Using gas price instead of base fee would more accurately reflect spend,\n        //  but is also subject to abuse if refunds were to be given automatically.\n        LiquidatorPoints memory points = liquidatorPoints[absorber];\n        points.numAbsorbs++;\n        points.numAbsorbed += safe64(accounts.length);\n        points.approxSpend += safe128(gasUsed * block.basefee);\n        liquidatorPoints[absorber] = points;\n    }\n\n    /**\n     * @dev Transfer user's collateral and debt to the protocol itself.\n     *\n     * Note on deactivated collateral:\n     *   All collateral is seized — including deactivated assets. The tokens are moved from\n     *   the user's balance to the protocol's reserves (balance zeroed, totals reduced).\n     *\n     *   For deactivated assets whose liquidationFactor has been set to 0:\n     *     - mulFactor(value, 0) == 0, so the asset's value does NOT offset the borrower's debt.\n     *     - The borrower receives less base-asset cashback than they would if the collateral\n     *       were still active, because only active collateral contributes to deltaValue.\n     *\n     *   After absorption, the protocol (Comet) holds the seized deactivated collateral tokens.\n     *   Governance can later handle them (e.g. via withdrawReserves or a future re-listing).\n     *   The borrower's assetsIn is reset to 0, debt is absorbed, and any residual value from\n     *   active collateral is credited as a positive base balance (cashback).\n     */\n    function absorbInternal(address absorber, address account) internal {\n        (bool liquidatable, uint256 basePrice, uint256[] memory assetPrices) = isLiquidatableInternal(account);\n        if (!liquidatable) revert NotLiquidatable();\n\n        UserBasic memory accountUser = userBasic[account];\n        int104 oldPrincipal = accountUser.principal;\n        int256 oldBalance = presentValue(oldPrincipal);\n        uint16 assetsIn = accountUser.assetsIn;\n        uint8 _reserved = accountUser._reserved;\n\n        AssetInfo memory assetInfo;\n        uint256 deltaValue;\n        address asset;\n        uint128 seizeAmount;\n        uint256 value;\n        for (uint8 i; i < numAssets; ) {\n            if (isInAsset(assetsIn, i, _reserved)) {\n                assetInfo = getAssetInfo(i);\n\n                // Skip assets with liquidationFactor == 0 — they are non-liquidatable and\n                // must not be seized during absorption. This serves three purposes:\n                // 1. The collateral remains with the borrower: non-liquidatable assets should\n                //    not be confiscated, and their value should not offset the account's debt.\n                // 2. Avoids calling getPrice() on their price feed below: if the oracle is\n                //    disabled or reverting, it would otherwise block absorption of the entire\n                //    account, preventing liquidation even for assets that *should* be seized.\n                // 3. mulFactor(value, 0) would contribute nothing to deltaValue anyway.\n                if (assetInfo.liquidationFactor == 0) {\n                    unchecked { ++i; }\n                    continue;\n                }\n\n                asset = assetInfo.asset;\n                seizeAmount = userCollateral[account][asset].balance;\n                userCollateral[account][asset].balance = 0;\n                totalsCollateral[asset].totalSupplyAsset -= seizeAmount;\n\n                value = mulPrice(seizeAmount, assetPrices[i], assetInfo.scale);\n                deltaValue += mulFactor(value, assetInfo.liquidationFactor);\n\n                emit AbsorbCollateral(absorber, account, asset, seizeAmount, value);\n            }\n            unchecked { ++i; }\n        }\n\n        uint256 deltaBalance = divPrice(deltaValue, basePrice, uint64(baseScale));\n        int256 newBalance = oldBalance + signed256(deltaBalance);\n        // New balance will not be negative, all excess debt absorbed by reserves\n        if (newBalance < 0) {\n            newBalance = 0;\n        }\n\n        int104 newPrincipal = principalValue(newBalance);\n        updateBasePrincipal(account, accountUser, newPrincipal);\n\n        // reset assetsIn\n        userBasic[account].assetsIn = 0;\n        userBasic[account]._reserved = 0;\n\n        (uint104 repayAmount, uint104 supplyAmount) = repayAndSupplyAmount(oldPrincipal, newPrincipal);\n\n        // Reserves are decreased by increasing total supply and decreasing borrows\n        //  the amount of debt repaid by reserves is `newBalance - oldBalance`\n        totalSupplyBase += supplyAmount;\n        totalBorrowBase -= repayAmount;\n\n        uint256 basePaidOut = unsigned256(newBalance - oldBalance);\n        uint256 valueOfBasePaidOut = mulPrice(basePaidOut, basePrice, uint64(baseScale));\n        emit AbsorbDebt(absorber, account, basePaidOut, valueOfBasePaidOut);\n\n        if (newPrincipal > 0) {\n            emit Transfer(address(0), account, presentValueSupply(baseSupplyIndex, unsigned104(newPrincipal)));\n        }\n    }\n\n    /**\n     * @notice Buy collateral from the protocol using base tokens, increasing protocol reserves\n       A minimum collateral amount should be specified to indicate the maximum slippage acceptable for the buyer.\n     * @param asset The asset to buy\n     * @param minAmount The minimum amount of collateral tokens that should be received by the buyer\n     * @param baseAmount The amount of base tokens used to buy the collateral\n     * @param recipient The recipient address\n     */\n    function buyCollateral(address asset, uint minAmount, uint baseAmount, address recipient) override external nonReentrant {\n        if (isBuyPaused()) revert Paused();\n\n        int reserves = getReserves();\n        if (reserves >= 0 && uint(reserves) >= targetReserves) revert NotForSale();\n\n        // Note: Re-entrancy can skip the reserves check above on a second buyCollateral call.\n        baseAmount = doTransferIn(baseToken, msg.sender, baseAmount);\n\n        uint collateralAmount = quoteCollateral(asset, baseAmount);\n        if (collateralAmount < minAmount) revert TooMuchSlippage();\n        if (collateralAmount > getCollateralReserves(asset)) revert InsufficientReserves();\n\n        // Note: Pre-transfer hook can re-enter buyCollateral with a stale collateral ERC20 balance.\n        //  Assets should not be listed which allow re-entry from pre-transfer now, as too much collateral could be bought.\n        //  This is also a problem if quoteCollateral derives its discount from the collateral ERC20 balance.\n        doTransferOut(asset, recipient, safe128(collateralAmount));\n\n        emit BuyCollateral(msg.sender, asset, baseAmount, collateralAmount);\n    }\n\n    /**\n     * @notice Gets the quote for a collateral asset in exchange for an amount of base asset\n     * @param asset The collateral asset to get the quote for\n     * @param baseAmount The amount of the base asset to get the quote for\n     * @return The quote in terms of the collateral asset\n     */\n    function quoteCollateral(address asset, uint baseAmount) override public view returns (uint) {\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\n\n        // NOTE: This getPrice() call is intentionally left unguarded. Unlike isBorrowCollateralized\n        // and isLiquidatable — where we skip zero-factor assets to prevent a broken price feed\n        // from paralyzing collateral checks — quoteCollateral is only called from buyCollateral,\n        // which is a voluntary action by an external buyer. If the asset's price feed is disabled\n        // or reverting, it is acceptable (and safer) for the quote to revert: the protocol should\n        // not sell collateral whose price it cannot verify.\n        uint256 assetPriceDiscounted = getPrice(assetInfo.priceFeed);\n\n        // Only apply the store front discount for assets that participate in liquidation\n        // (i.e. liquidationFactor > 0). Assets with liquidationFactor == 0 are non-liquidatable:\n        // they are skipped during absorption (see absorbInternal) and therefore should not\n        // receive a liquidation discount when purchased via buyCollateral.\n        //\n        // Additionally, if liquidationFactor == 0 the discount math would compute\n        // discountFactor = storeFrontPriceFactor * (FACTOR_SCALE - 0) / FACTOR_SCALE\n        //                = storeFrontPriceFactor,\n        // and when storeFrontPriceFactor == FACTOR_SCALE (100%) that yields\n        // assetPrice = assetPrice * (FACTOR_SCALE - FACTOR_SCALE) / FACTOR_SCALE = 0,\n        // which would cause a division-by-zero revert in the return statement below.\n        //\n        // By skipping the discount, the protocol sells such collateral at the fair oracle\n        // price — no liquidation incentive is needed for non-liquidatable assets.\n        // Market price will be used if liquidationFactor == 0   \n        if (assetInfo.liquidationFactor != 0) {\n            // Store front discount is derived from the collateral asset's liquidationFactor and storeFrontPriceFactor\n            // discount = storeFrontPriceFactor * (1e18 - liquidationFactor)\n            uint256 discountFactor = mulFactor(storeFrontPriceFactor, FACTOR_SCALE - assetInfo.liquidationFactor);\n            assetPriceDiscounted = mulFactor(assetPriceDiscounted, FACTOR_SCALE - discountFactor);\n        }\n\n        uint256 basePrice = getPrice(baseTokenPriceFeed);\n        // # of collateral assets\n        // = (TotalValueOfBaseAmount / DiscountedPriceOfCollateralAsset) * assetScale\n        // = ((basePrice * baseAmount / baseScale) / assetPrice) * assetScale\n        return basePrice * baseAmount * assetInfo.scale / assetPriceDiscounted / baseScale;\n    }\n\n    /**\n     * @notice Withdraws base token reserves if called by the governor\n     * @param to An address of the receiver of withdrawn reserves\n     * @param amount The amount of reserves to be withdrawn from the protocol\n     */\n    function withdrawReserves(address to, uint amount) override external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        int reserves = getReserves();\n        if (reserves < 0 || amount > unsigned256(reserves)) revert InsufficientReserves();\n\n        doTransferOut(baseToken, to, amount);\n\n        emit WithdrawReserves(to, amount);\n    }\n\n    /**\n     * @notice Sets Comet's ERC20 allowance of an asset for a manager\n     * @dev Only callable by governor\n     * @dev Note: Setting the `asset` as Comet's address will allow the manager\n     * to withdraw from Comet's Comet balance\n     * @dev Note: For USDT, if there is non-zero prior allowance, it must be reset to 0 first before setting a new value in proposal\n     * @param asset The asset that the manager will gain approval of\n     * @param manager The account which will be allowed or disallowed\n     * @param amount The amount of an asset to approve\n     */\n    function approveThis(address manager, address asset, uint amount) override external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        IERC20NonStandard(asset).approve(manager, amount);\n    }\n\n    /**\n     * @notice Get the total number of tokens in circulation\n     * @dev Note: uses updated interest indices to calculate\n     * @return The supply of tokens\n     **/\n    function totalSupply() override external view returns (uint256) {\n        (uint64 baseSupplyIndex_, ) = accruedInterestIndices(getNowInternal() - lastAccrualTime);\n        return presentValueSupply(baseSupplyIndex_, totalSupplyBase);\n    }\n\n    /**\n     * @notice Get the total amount of debt\n     * @dev Note: uses updated interest indices to calculate\n     * @return The amount of debt\n     **/\n    function totalBorrow() override external view returns (uint256) {\n        (, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime);\n        return presentValueBorrow(baseBorrowIndex_, totalBorrowBase);\n    }\n\n    /**\n     * @notice Query the current positive base balance of an account or zero\n     * @dev Note: uses updated interest indices to calculate\n     * @param account The account whose balance to query\n     * @return The present day base balance magnitude of the account, if positive\n     */\n    function balanceOf(address account) override public view returns (uint256) {\n        (uint64 baseSupplyIndex_, ) = accruedInterestIndices(getNowInternal() - lastAccrualTime);\n        int104 principal = userBasic[account].principal;\n        return principal > 0 ? presentValueSupply(baseSupplyIndex_, unsigned104(principal)) : 0;\n    }\n\n    /**\n     * @notice Query the current negative base balance of an account or zero\n     * @dev Note: uses updated interest indices to calculate\n     * @param account The account whose balance to query\n     * @return The present day base balance magnitude of the account, if negative\n     */\n    function borrowBalanceOf(address account) override public view returns (uint256) {\n        (, uint64 baseBorrowIndex_) = accruedInterestIndices(getNowInternal() - lastAccrualTime);\n        int104 principal = userBasic[account].principal;\n        return principal < 0 ? presentValueBorrow(baseBorrowIndex_, unsigned104(-principal)) : 0;\n    }\n\n    /**\n     * @notice Fallback to calling the extension delegate for everything else\n     */\n    fallback() external payable {\n        address delegate = extensionDelegate;\n        assembly {\n            calldatacopy(0, 0, calldatasize())\n            let result := delegatecall(gas(), delegate, 0, calldatasize(), 0, 0)\n            returndatacopy(0, 0, returndatasize())\n            switch result\n            case 0 { revert(0, returndatasize()) }\n            default { return(0, returndatasize()) }\n        }\n    }\n}","deployed_bytecode":"0x60806040526004361015610018575b61001661511f565b005b60003560e01c8063042e02cf146106d05780630546e6ec146106c75780630902f1ac146106be5780630bc47ad1146106b55780630c340a24146106ac57806318160ddd146106a3578063189bb2f11461069a5780631c9f7fb9146106915780631f5954bd14610688578063214435621461067f57806323b872dd1461067657806324a3d6221461066d578063264413181461066457806329c5a1a01461065b5780632a48cf12146106525780632b92a07d146106495780632d05670b146106405780632e04b8e714610637578063300e6beb1461062e578063313ce5671461062557806332176c491461061c578063374c49b41461061357806338aa813f1461060a5780633b3bec2e1461060157806341976e09146105f85780634232cd63146105ef578063439e2e45146105e657806344c1e5eb146105dd57806344c35d07146105d457806344ff241d146105cb5780634a95a76a146105c257806350a1efea146105b957806359e017bd146105b05780635a94b8d1146105a757806367800b5f1461059e5780636f678cce1461059557806370a082311461058c5780637914acc7146105835780637ac88ed11461057a5780637eb7113114610571578063804de71f146105685780638285ef401461055f5780638a5704df146105565780638d5d814c1461054d57806390323177146105445780639241a5611461053b5780639364e18a1461053257806394920cca146105295780639545e4de146105205780639ae3890c146105175780639ea99a5a1461050e5780639fa83b5a146105055780639ff567f8146104fc578063a1654379146104f3578063a1a1ef43146104ea578063a46fe83b146104e1578063a5b4ff79146104d8578063a9059cbb146104cf578063aba7f15e146104c6578063ad14777c146104bd578063b2a7a721146104b4578063bfe69c8d146104ab578063c04a5b06146104a2578063c1ee2c1814610499578063c3b35a7e14610490578063c3cecfd214610487578063c55dae631461047e578063c5fa15cf14610475578063c82643b41461046c578063c8c7fe6b14610463578063cde680411461045a578063cdfadab614610451578063ce26a7b014610448578063d8e5f6111461043f578063d955759d14610436578063dc4abafd1461042d578063e1066c9014610424578063e30ca4041461041b578063e372f03a14610412578063e478795d14610409578063e4e6e77914610400578063e719dc74146103f7578063e7dad6bd146103ee578063f2b9fdb8146103e5578063f3fef3a3146103dc5763fddc530f0361000e576103d7611e89565b61000e565b506103d7611e54565b506103d7611e20565b506103d7611dda565b506103d7611db7565b506103d7611c2e565b506103d7611b43565b506103d7611afd565b506103d7611ad9565b506103d7611ab2565b506103d7611a3f565b506103d7611a20565b506103d76119f9565b506103d76119d5565b506103d76119ba565b506103d761199e565b506103d7611975565b506103d7611946565b506103d76118d8565b506103d7611892565b506103d761182d565b506103d7611809565b506103d76117e3565b506103d76117bc565b506103d7611796565b506103d761176f565b506103d76116ca565b506103d761168e565b506103d7611638565b506103d76115fc565b506103d76115bd565b506103d7611596565b506103d7611555565b506103d761152d565b506103d76114fc565b506103d76114c0565b506103d76114a5565b506103d761148a565b506103d761144e565b506103d7611412565b506103d76113d6565b506103d76113b1565b506103d761138a565b506103d7611367565b506103d7611306565b506103d76112ca565b506103d76112ae565b506103d7611282565b506103d7611246565b506103d761121e565b506103d76111fa565b506103d76111d3565b506103d7611197565b506103d7611141565b506103d761111d565b506103d76110f6565b506103d76110b0565b506103d7610f31565b506103d7610ee8565b506103d7610ec4565b506103d7610ea1565b506103d7610e79565b506103d7610e44565b506103d7610d78565b506103d7610d50565b506103d7610d14565b506103d7610cd5565b506103d7610c99565b506103d7610c5b565b506103d7610c1f565b506103d7610bca565b506103d7610b1c565b506103d7610ae5565b506103d7610a90565b506103d7610a13565b506103d76109b0565b506103d761095f565b506103d7610923565b506103d761089d565b506103d7610861565b506103d76107f5565b506103d76107af565b506103d7610776565b506103d7610752565b506103d761072e565b506103d76106ef565b6001600160a01b038116036106ea57565b600080fd5b50346106ea5760203660031901126106ea576020610717600435610712816106d9565b613063565b50506040519015158152f35b60009103126106ea57565b50346106ea5760003660031901126106ea5760206080600854161515604051908152f35b50346106ea5760003660031901126106ea57602061076e612b7a565b604051908152f35b50346106ea5760003660031901126106ea5760206001805460f81c161515604051908152f35b6001600160a01b03909116815260200190565b50346106ea5760003660031901126106ea576040517f000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a026001600160a01b03168152602090f35b50346106ea5760003660031901126106ea57602066038d7ea4c6800061085861081c612170565b61083f6001549161083964ffffffffff91828560d01c169061226c565b16612520565b506001600160401b0316906001600160681b031661229a565b04604051908152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576000806003193601126109205760015464ffffffffff8160d01c1661090f5764ffffffffff60d01b6108d3612170565b64ffffffffff60d01b1990921660d09290921b161760015580546001600160801b0319166e038d7ea4c6800000038d7ea4c68000178155604051f35b60405162dc149f60e41b8152600490fd5b80fd5b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000853a0d2313c00008152f35b50346106ea5760003660031901126106ea5760206001600854161515604051908152f35b908160609103126106ea578035610999816106d9565b91604060208301356109aa816106d9565b92013590565b50346106ea576109f66109c4366004610983565b91906109ce613752565b7f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029139133614053565b600060008051602061517f83398151915255602060405160018152f35b50346106ea5760003660031901126106ea576040517f0000000000000000000000003cb4653f3b45f448d9100b118b75a1503281d2ee6001600160a01b03168152602090f35b91908260809103126106ea578135610a70816106d9565b916020810135610a7f816106d9565b91606060408301356109aa816106d9565b50346106ea57610ab6610aa4366004610a59565b92610ab0929192613752565b336145af565b600060008051602061517f83398151915255005b908160209103126106ea573562ffffff811681036106ea5790565b50346106ea576020610b12610afb366004610aca565b60085460601c600162ffffff8093161b1616151590565b6040519015158152f35b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000000001a942ee5c58152f35b91908260409103126106ea5760208235610b71816106d9565b920135610b7d816106d9565b90565b9060018060a01b0316600052602052604060002090565b6001600160801b031690565b546001600160801b031690565b6001600160801b0391821681529116602082015260400190565b50346106ea57610c1b610bff610be1366004610b58565b6001600160a01b039091166000908152600660205260409020610b80565b54604051918291608081901c906001600160801b031683610bb0565b0390f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000348078298152f35b50346106ea5760203660031901126106ea57600435610c79816106d9565b60018060a01b031660005260046020526020604060002054604051908152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000018152f35b50346106ea5760003660031901126106ea57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000006168152f35b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000000048c273950008152f35b50346106ea5760203660031901126106ea57602061076e600435610d73816106d9565b6150d7565b50346106ea5760203660031901126106ea576020610b12600435610d9b816106d9565b612cdf565b6001600160401b031690565b610e429092919260e08061010083019560ff815116845260018060a01b03806020830151166020860152604082015116604085015260018060401b036060820151166060850152610e0c6080820151608086019060018060401b03169052565b60a0818101516001600160401b03169085015260c0818101516001600160401b03169085015201516001600160801b0316910152565b565b50346106ea5760203660031901126106ea57610c1b610e6d600435610e68816106d9565b6120ec565b60405191829182610dac565b50346106ea5760203660031901126106ea57602061076e600435610e9c816106d9565b6129d7565b50346106ea57610ab6610eb5366004610983565b91610ebe613752565b3361366a565b50346106ea57610ab6610ed8366004610983565b91610ee1613752565b3333614053565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000f42408152f35b359081151582036106ea57565b50346106ea5760a03660031901126106ea57610f4d6004610f24565b610f576024610f24565b610f616044610f24565b91610f6c6064610f24565b92610f776084610f24565b60018060a01b03807f000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a02163314159081611083575b50611072577f3be39979091ae7ca962aa1c44e645f2df3c221b79f324afa5f44aedc8d2f690d9461106d92611038610ff56000610fe788613278565b9060ff8080931691161b1690565b6110036001610fe78a613278565b176110126002610fe785613278565b176110216003610fe786613278565b176110306004610fe787613278565b176001613255565b6040519586958693909594919260809360a0860197151586521515602086015215156040850152151560608401521515910152565b0390a1005b6040516282b42960e81b8152600490fd5b90507f0000000000000000000000003cb4653f3b45f448d9100b118b75a1503281d2ee1633141538610fab565b50346106ea5760003660031901126106ea576040517f0000000000000000000000000d4bd55a755134950027ce1f43190a354e648e206001600160a01b03168152602090f35b50346106ea5760003660031901126106ea57602062ffffff60085460601c16604051908152f35b50346106ea5760003660031901126106ea576020604051671bc16d674ec800008152f35b50346106ea5760203660031901126106ea5760043561115f816106d9565b6001600160a01b031660009081526002602052604090819020549051908190610c1b90608081901c906001600160801b031683610bb0565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000440ab57f8152f35b50346106ea5760003660031901126106ea576020600460015460f81c161515604051908152f35b50346106ea5760003660031901126106ea5760206040600854161515604051908152f35b50346106ea5760203660031901126106ea57602061076e600435611241816106d9565b615079565b50346106ea5760003660031901126106ea5760206040517f000000000000000000000000000000000000000000000000000000001c59cb9f8152f35b50346106ea5760403660031901126106ea57602061076e6004356112a5816106d9565b60243590614f40565b50346106ea5760003660031901126106ea57602061076e612949565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000017989a464c8152f35b50346106ea5760003660031901126106ea57602066038d7ea4c6800061085861132d612170565b61134a6001549161083964ffffffffff91828560d01c169061226c565b6001600160401b03169160681c6001600160681b0316905061229a565b50346106ea5760003660031901126106ea57602060088054161515604051908152f35b50346106ea5760003660031901126106ea576020600860015460f81c161515604051908152f35b50346106ea57610ab66113c5366004610a59565b926113d1929192613752565b61366a565b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000c7d713b49da00008152f35b50346106ea5760003660031901126106ea5760206040517f000000000000000000000000000000000000000000000000000000003b9aca008152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576020610b126114a0366004610aca565b6132b4565b50346106ea576020610b126114bb366004610aca565b61329d565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760203660031901126106ea57602061151b600435612842565b6040516001600160401b039091168152f35b50346106ea5760203660031901126106ea57602061076e600435611550816106d9565b612a82565b50346106ea57602060ff61158a61156d366004610b58565b6001600160a01b0390911660009081526003855260409020610b80565b54166040519015158152f35b50346106ea5760003660031901126106ea576020600260015460f81c161515604051908152f35b50346106ea5760003660031901126106ea57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000005168152f35b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000c7d713b49da00008152f35b50346106ea5760403660031901126106ea576109f6600435611659816106d9565b611661613752565b602435907f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913903333614053565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000038d7ea4c680008152f35b50346106ea576116db366004610983565b91906001600160a01b03907f000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a0282163303611072571691823b156106ea5761173c926000928360405180968195829463095ea7b360e01b8452600484016147fe565b03925af18015611762575b61174d57005b8061175c600061001693611f01565b80610723565b61176a611fb0565b611747565b50346106ea5760003660031901126106ea57602062ffffff60085460181c16604051908152f35b50346106ea5760203660031901126106ea576100166004356117b7816106d9565b6121e4565b50346106ea5760003660031901126106ea57602062ffffff60085460301c16604051908152f35b50346106ea57610ab66117f7366004610a59565b92611803929192613752565b33614053565b50346106ea57610ab661181d366004610983565b91611826613752565b33336145af565b50346106ea5760403660031901126106ea5760043561184b816106d9565b602435906001600160401b03908183116106ea57366023840112156106ea5782600401359182116106ea573660248360051b850101116106ea576024610016930190614a37565b50346106ea5760003660031901126106ea576040517f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029136001600160a01b03168152602090f35b50346106ea5760203660031901126106ea576004356118f6816106d9565b60018060a01b0316600052600760205260806040600020546040519063ffffffff8116825260018060401b038160201c166020830152600180841b038160601c16604083015260e01c6060820152f35b50346106ea5760003660031901126106ea5760206010600854161515604051908152f35b60ff8116036106ea57565b50346106ea5760203660031901126106ea57610c1b610e6d6004356119998161196a565b611fbd565b50346106ea576020610b126119b4366004610b58565b90611ead565b50346106ea576020610b126119d0366004610aca565b613286565b50346106ea5760003660031901126106ea5760206002600854161515604051908152f35b50346106ea5760003660031901126106ea576020601060015460f81c161515604051908152f35b50346106ea5760203660031901126106ea57602061151b6004356125d8565b50346106ea5760203660031901126106ea57600435611a5d816106d9565b60018060a01b0316600052600560205260a06040600020546040519080600c0b825260018060401b03808260681c1660208401528160a81c16604083015261ffff8160e81c16606083015260f81c6080820152f35b50346106ea5760003660031901126106ea57602062ffffff60085460481c16604051908152f35b50346106ea5760003660031901126106ea57602062ffffff60085416604051908152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000090dcbcdc49195776b8807f01d9f127f9317674bb6001600160a01b03168152602090f35b50346106ea5760403660031901126106ea57600435611b61816106d9565b602435906001600160a01b037f000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a028116330361107257611b9e612b7a565b60008112908115611c1c575b50611c0a5781611bfc847fec4431f2ba1a9382f6b0c4352b888cba6f7db91667d9f776abe5ad8ddc5401b6947f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913614819565b6040519384521691602090a2005b60405163128bd24d60e31b8152600490fd5b611c269150614f35565b831138611baa565b50346106ea5760803660031901126106ea57600435611c4c816106d9565b60643590611c59826106d9565b611c61613752565b601060015460f81c16611da557611c76612b7a565b60008112159081611d7a575b50611d6857611cb4604435337f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913613b50565b90611cbf8282614f40565b926024358410611d5657611cd282612a82565b8411611c0a577ff891b2a411b0e66a5f0a6ff1368670fefa287a13f541eb633a386a1a9cc7046b91611d19611d3c92611d12611d0d8861372c565b610b97565b9083614819565b6040805194855260208501959095526001600160a01b0316933393918291820190565b0390a3610016600060008051602061517f83398151915255565b60405163fa6ad35560e01b8152600490fd5b604051631d99ddbf60e01b8152600490fd5b90507f0000000000000000000000000000000000000000000000000000048c27395000111538611c82565b6040516313d0ff5960e31b8152600490fd5b50346106ea5760003660031901126106ea57602080600854161515604051908152f35b50346106ea5760003660031901126106ea576040517f0000000000000000000000003e6d1cca8eee6d02f1f578b613374eb53e6823b46001600160a01b03168152602090f35b50346106ea5760403660031901126106ea57610ab6600435611e41816106d9565b611e49613752565b60243590333361366a565b50346106ea5760403660031901126106ea57610ab6600435611e75816106d9565b611e7d613752565b602435903333336145af565b50346106ea5760003660031901126106ea5760206004600854161515604051908152f35b6001600160a01b03808316911690811491908215611eca57505090565b60ff925090611ee59160005260036020526040600020610b80565b541690565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017611f2457604052565b611f2c611eea565b604052565b60405190611f4161010083611f01565b8160e06000918281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b5190610e428261196a565b5190610e42826106d9565b51906001600160401b03821682036106ea57565b51906001600160801b03821682036106ea57565b506040513d6000823e3d90fd5b611fc5611f31565b5060405163c8c7fe6b60e01b815260ff91909116600482015261010080826024817f00000000000000000000000090dcbcdc49195776b8807f01d9f127f9317674bb6001600160a01b03165afa9182156120df575b60009261202657505090565b90918282813d83116120d8575b61203d8183611f01565b81010312610920575060e06120d0916120596040519485611f01565b61206281611f72565b845261207060208201611f7d565b602085015261208160408201611f7d565b604085015261209260608201611f88565b60608501526120a360808201611f88565b60808501526120b460a08201611f88565b60a08501526120c560c08201611f88565b60c085015201611f9c565b60e082015290565b503d612033565b6120e7611fb0565b61201a565b906120f5611f31565b5060009060ff92837f000000000000000000000000000000000000000000000000000000000000000516925b838582161061213c57604051633640530560e01b8152600490fd5b61214581611fbd565b60208101516001600160a01b0384811691161461216757506001018416612121565b93505050915090565b600160281b4210156121875764ffffffffff421690565b604051633d32ffdb60e01b8152600490fd5b906040516121a860a082611f01565b608081935480600c0b835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c910152565b610e42906121f06122f1565b60018060a01b038116600052600560205260406000206040519061221560a083611f01565b549182600c0b9283835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c6080830152613504565b50634e487b7160e01b600052601160045260246000fd5b64ffffffffff9182169116818110612282570390565b61228a612255565b0390565b6001600160681b031690565b80600019048211811515166122ad570290565b6122b5612255565b0290565b6001600160401b03918216919081169082900381116122d6570190565b6122de612255565b0190565b60681c6001600160681b031690565b6122f9612170565b61232361231961231360015464ffffffffff9060d01c1690565b8361226c565b64ffffffffff1690565b908161232d575050565b8161238461233d610e4294612520565b60008054600160401b600160801b03191660409290921b600160401b600160801b0316919091178155919082546001600160401b0319166001600160401b03909116178255565b61238f60015461228e565b7f000000000000000000000000000000000000000000000000000000003b9aca0092906001600160681b031683811015612484575b506123d86123d36001546122e2565b61228e565b9283101561240c575b50506001805464ffffffffff60d01b191660d09390931b64ffffffffff60d01b169290921790915550565b61244d61244861247c9461244361245c947f000000000000000000000000000000000000000000000000000000000000000061229a565b6132de565b6124fa565b825460c01c6122b9565b6122b9565b81546001600160c01b031660c09190911b6001600160c01b031916179055565b3880806123e1565b6124ce6124bb6124486124f493612443867f000000000000000000000000000000000000000000000000000000000000000061229a565b845460801c6001600160401b03166122b9565b8354600160801b600160c01b03191660809190911b600160801b600160c01b0316178355565b386123c4565b6001600160401b039081811161250e571690565b6040516372a1cb5160e11b8152600490fd5b6000546001600160401b03604082901c81169392918116919081612545575b50509190565b8161259861259261257297946125a46125aa9761259e8761257961259e9961256b612949565b9e8f6125d8565b169d612842565b169b612598612592670de0b6b3a7640000998a9361229a565b8461229a565b046124fa565b906122b9565b9861229a565b91388061253f565b908160209103126106ea575190565b811981116122d6570190565b818110612282570390565b6125e360015461228e565b6001600160681b038116156127e9578115806127c0575b6126ff575b507f0000000000000000000000000000000000000000000000000c7d713b49da00008082116126895750612448670de0b6b3a7640000612662610b7d937f00000000000000000000000000000000000000000000000000000000440ab57f61229a565b047f00000000000000000000000000000000000000000000000000000000000000006125c1565b610b7d916126f96126d3836126cd670de0b6b3a7640000612662612448977f00000000000000000000000000000000000000000000000000000000440ab57f61229a565b936125cd565b7f00000000000000000000000000000000000000000000000000000017989a464c6132cb565b906125c1565b6127139061270e600054610da0565b61281d565b6040516370a0823160e01b81529060208280612732306004830161079c565b03817f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029136001600160a01b03165afa9182156127b3575b600092612783575b50101561277d57386125ff565b50600090565b6127a591925060203d81116127ac575b61279d8183611f01565b8101906125b2565b9038612770565b503d612793565b6127bb611fb0565b612768565b507f000000000000000000000000000000000000000000000000000000000000000015156125fa565b5050600090565b50634e487b7160e01b600052601260045260246000fd5b8115612811570490565b6128196127f0565b0490565b66038d7ea4c6800091612819916001600160401b0316906001600160681b031661229a565b60015460681c6001600160681b03161561277d577f0000000000000000000000000000000000000000000000000c7d713b49da00008082116128df5750612448670de0b6b3a76400006128b8610b7d937f000000000000000000000000000000000000000000000000000000003480782961229a565b047f000000000000000000000000000000000000000000000000000000001c59cb9f6125c1565b610b7d916126f9612923836126cd670de0b6b3a76400006128b8612448977f000000000000000000000000000000000000000000000000000000003480782961229a565b7f0000000000000000000000000000000000000000000000000000001a942ee5c56132cb565b60005460015466038d7ea4c680009061298b906001600160681b036001600160401b038461297b82881684861661229a565b049560401c169160681c1661229a565b0481612998575050600090565b670de0b6b3a76400009080600019048211811515166129b657020490565b6129be612255565b020490565b51906001600160501b03821682036106ea57565b604051633fabe5a360e21b81529060a090829060049082906001600160a01b03165afa908115612a75575b600091612a29575b506000811315612a175790565b60405163fd1ee34960e01b8152600490fd5b9060a0823d8211612a6d575b81612a4260a09383611f01565b810103126109205750612a54816129c3565b50612a666080602083015192016129c3565b5038612a0a565b3d9150612a35565b612a7d611fb0565b612a02565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa918215612afd575b600092612add575b506000908152600260205260409020546001600160801b031690818110612282570390565b612af691925060203d81116127ac5761279d8183611f01565b9038612ab8565b612b05611fb0565b612ab0565b600082128015600160ff1b8401831216612b34575b6001600160ff1b038301821316612282570390565b612b3c612255565b612b1f565b6000811280156001600160ff1b03839003841316612b6d575b600160ff1b8290038312166122d6570190565b612b75612255565b612b5a565b610b7d612b85612170565b612ba8612ba36123196001549364ffffffffff8560d01c169061226c565b612520565b90604051926370a0823160e01b845260208480612bc8306004830161079c565b03817f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029136001600160a01b03165afa938415612c9d575b600094612c65575b5091612c59612c53612c5393612c4c612c5f9666038d7ea4c680009260018060401b0384612c3f8260018060681b03941684861661229a565b0497169160681c1661229a565b0495612caa565b91612caa565b90612b0a565b90612b41565b612c5f93919450612c53612c5393612c4c612c90612c599460203d81116127ac5761279d8183611f01565b9794965050935050612c06565b612ca5611fb0565b612bfe565b6001600160ff1b038111612cbb5790565b60405163e7e828ad60e01b8152600490fd5b60ff6001911660ff81146122d6570190565b612cf4612ced826005610b80565b54600c0b90565b6000918282600c0b1215612f1e57612d1b612d10826005610b80565b5460e81c61ffff1690565b612d39612d33612d2c846005610b80565b5460f81c90565b93612f5d565b612d98612d657f0000000000000000000000003e6d1cca8eee6d02f1f578b613374eb53e6823b46129d7565b6001600160401b03927f00000000000000000000000000000000000000000000000000000000000f424084169190613329565b93612da1611f31565b5060ff927f00000000000000000000000000000000000000000000000000000000000000058416875b8186821610612ddf5750505050505050121590565b612dea84828561340f565b612dfd575b612df890612ccd565b612dca565b9688811215612f1057612e0f88611fbd565b612e26610afb612e20835160ff1690565b60ff1690565b612ee257608081019086612e3a8351610da0565b1615612ed65791612c5f612ec9612ece93612ec3612ebe612eb7612df8988f612e7f612e6a612e84926006610b80565b60208401516001600160a01b03165b90610b80565b610ba3565b90612ea86060612ea0610e9c604085015160018060a01b031690565b920151610da0565b916001600160801b0316613309565b9251610da0565b610da0565b906132cb565b612caa565b979050612def565b505096612df890612ccd565b60200151612f0c906001600160a01b0316604051637050033f60e01b81529182916004830161079c565b0390fd5b505050505050505050600190565b505050600190565b600c0b6001600160671b03198114612f3f575b60000390565b612f47612255565b612f39565b600160ff1b8114612f3f5760000390565b6000600c82900b12612f9d57600054610b7d9166038d7ea4c6800091612f97916001600160401b03909116906001600160681b031661229a565b04612caa565b612fcd612ec9610b7d92612fbe60018060401b0360005460401c1691612f26565b6001600160681b03169061281d565b612f4c565b6020906001600160401b038111612feb575b60051b0190565b612ff3611eea565b612fe4565b9061300282612fd2565b61300f6040519182611f01565b8281528092613020601f1991612fd2565b0190602036910137565b50634e487b7160e01b600052603260045260246000fd5b6020918151811015613056575b60051b010190565b61305e61302a565b61304e565b90613072612ced836005610b80565b916000918284600c0b121561324a5760ff92837f000000000000000000000000000000000000000000000000000000000000000516906130b182612ff8565b906130c0612d10866005610b80565b936130cf612d2c876005610b80565b916131026130fc7f0000000000000000000000003e6d1cca8eee6d02f1f578b613374eb53e6823b46129d7565b99612f5d565b6001600160401b03939061313b907f00000000000000000000000000000000000000000000000000000000000f42408616908c90613329565b96613144611f31565b50825b8a8116888110156132385761315d84838561340f565b613171575b5061316c90612ccd565b613147565b848a929a1215613227576131848a611fbd565b60a08101918c896131958551610da0565b16156132195761321293612ec3612ebe612eb78e87612ea86060613209612c5f9a61320361316c9f9d6131f0612ec99d6131de610e9c6040612e7f95015160018060a01b031690565b6131e8868c613041565b526006610b80565b60208801516001600160a01b0316612e79565b95613041565b51920151610da0565b9890613162565b505050509761316c90612ccd565b505050509450945050935050929190565b50505050949350945050935012929190565b919250508190606090565b80546001600160f81b031660f89290921b6001600160f81b031916919091179055565b60009015610b7d5750600190565b60085460181c600162ffffff8093161b1616151590565b60085460301c600162ffffff8093161b1616151590565b60085460481c600162ffffff8093161b1616151590565b670de0b6b3a7640000916128199161229a565b612807907f00000000000000000000000000000000000000000000000000000000000f42409061229a565b906133139161229a565b6001600160401b03909116908115612811570490565b919061333490612caa565b6000808413939082136001600160ff1b038582168482048411166133f0575b600160ff1b956000851291859183168589058312166133e3575b600085129384168289058612166133d6575b0583129116166133c9575b6001600160401b039092169291029082156133bc575b81146000198314166133b0570590565b6133b8612255565b0590565b6133c46127f0565b6133a0565b6133d1612255565b61338a565b6133de612255565b61337f565b6133eb612255565b61336d565b6133f8612255565b613353565b60ff9182169116818110612282570390565b9060ff16916010831060001461342e5750600161ffff921b1616151590565b90506018821061343f575050600090565b600160ff8093600f1901161b1616151590565b6001600160401b039182169116818110612282570390565b805461ffff60e81b191660e89290921b61ffff60e81b16919091179055565b81518154602084015160408501516001600160e81b03199092166001600160681b039093169290921760689290921b600160681b600160a81b03169190911760a89190911b600160a81b600160e81b03161781556060820151610e429260ff91608091906134fb9061ffff168561346a565b01511690613255565b61361390610e42936135178451600c0b90565b600c82900b855260009182918683600c83900b811361362a5761359c6135756135e294613566612ebe6135c3966135606020612ea0612448995460018060401b039060801c1690565b90613452565b906001600160681b031661229a565b7f00000000000000000000000000000000000000000000000000038d7ea4c6800090612807565b7f000000000000000000000000000000000000000000000000000000000000000190612807565b6135d560408901916124578351610da0565b6001600160401b03169052565b600c0b12613618575461360c9060801c6001600160401b03165b6001600160401b03166020850152565b6005610b80565b613489565b546136259060c01c6135fc565b61360c565b61359c613575613665946136606123d361228e61365a612ebe6135c3996135606020612ea06124489c5460c01c90565b93612f26565b61229a565b6135e2565b92916001805460f81c16611da5576136896136853386611ead565b1590565b611072576001600160a01b038181167f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913909116036136fa575060088054166136e957610e429260001983036137ff5791506136e3816150d7565b916137ff565b6040516230dad960e61b8152600490fd5b9060046008949394541661371a57613714610e429461372c565b92613d74565b60405163b4abb28d60e01b8152600490fd5b6001600160801b0390818111613740571690565b60405163762ea71160e11b8152600490fd5b60008051602061517f83398151915260018154146137705760019055565b60405163139b643560e21b8152600490fd5b6001600160681b03918216919081169082900381116122d6570190565b80546001600160681b0319166001600160681b03909216919091179055565b6001600160681b039182169116818110612282570390565b8054600160681b600160d01b03191660689290921b600160681b600160d01b0316919091179055565b61382e6138ac9293827f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913613b50565b6138366122f1565b6138b961384c613847866005610b80565b612199565b8051600c0b906138b361387c61387561387061386786612f5d565b612c5f89612caa565b61393e565b8094613ad4565b979061389c6138958a61389060015461228e565b613782565b600161379f565b6138a76001546122e2565b6137be565b60016137d6565b86613504565b6040519081526001600160a01b0393841693849216907fd1cf3d156d5f8f0d50f6c122ed609cec09d35c9b9fb3fff6ea0959134dae424e90602090a36001600160681b038116613907575050565b60008051602061515f83398151915261393961392960009361270e8554610da0565b6040519081529081906020820190565b0390a3565b6000811261396457600054610b7d9161395f916001600160401b03166139ed565b613a63565b6139c161395f610b7d9261398560018060401b0360005460401c1691612f4c565b6139aa826000199266038d7ea4c68000908085048211811515166139e0575b026125c1565b600181106139d3575b82156139c6575b0104613a3d565b612f26565b6139ce6127f0565b6139ba565b6139db612255565b6139b3565b6139e8612255565b6139a4565b90610b7d9166038d7ea4c68000908260001904821183151516613a30575b6001600160401b0316918215613a23575b0204613a3d565b613a2b6127f0565b613a1c565b613a38612255565b613a0b565b6001600160681b0390818111613a51571690565b604051630dc7925560e11b8152600490fd5b6001600160681b03166001600160671b038111613a8057600c0b90565b604051639369ae3560e01b8152600490fd5b600c91820b910b6000821280156001600160671b03198401831216613ac7575b6001600160671b038301821316612282570390565b613acf612255565b613ab2565b91909180600c0b83600c0b818112613b4357600012613b075750613af89192613a92565b6001600160681b031690600090565b600013613b2a57613b189192613a92565b6000916001600160681b039190911690565b613b3390612f26565b6001600160681b03908116921690565b5050509050600090600090565b6040516370a0823160e01b8082529390926020926001600160a01b03169190838580613b7f306004830161079c565b0381865afa948515613cbd575b600095613c9e575b50823b156106ea576040516323b872dd60e01b81526001600160a01b03919091166004820152306024820152604481019190915260008160648183865af18015613c91575b613c7c575b503d8015613c7357602014613bf257600080fd5b816000803e6000515b15613c615781610b7d9460405192839182528180613c1c306004830161079c565b03915afa918215613c54575b600092613c37575b50506125cd565b613c4d9250803d106127ac5761279d8183611f01565b3880613c30565b613c5c611fb0565b613c28565b60405163073d1efd60e51b8152600490fd5b50600019613bfb565b8061175c6000613c8b93611f01565b38613bde565b613c99611fb0565b613bd9565b613cb6919550843d86116127ac5761279d8183611f01565b9338613b94565b613cc5611fb0565b613b8c565b90604051613cd9604082611f01565b91546001600160801b038116835260801c6020830152565b6001600160801b03918216919081169082900381116122d6570190565b80546001600160801b0319166001600160801b03909216919091179055565b90602060018060801b0391613d458382511685613d0e565b0151825490911660809190911b6001600160801b031916179055565b6001600160801b03909116815260200190565b919092613d80826120ec565b805160ff16613d8e8161329d565b613eca5750613d9c856121e4565b6001600160801b0391613dbb90613db69084168686613b50565b61372c565b92613dcf613dca826002610b80565b613cca565b92613df3613de686613de18751610b97565b613cf1565b6001600160801b03168552565b613dfd8451610b97565b90613e0e611d0d60e0860151610b97565b911611613eb857613e93613e8185613eb394613e8d7ffa56f7b24f17183d81894d3ac2ee654e3c26388d17a28dbd9549b8114304e1f497613e8887613e628e613e6e613e67612e7f85613e62856006610b80565b610b80565b9889613cf1565b988995613e7c856002610b80565b613d2d565b6006610b80565b613d0e565b89613ee7565b6040516001600160a01b0391821696821695909116939091829182613d61565b0390a4565b604051637ac7b99d60e11b8152600490fd5b6040516335d1e86560e11b815260ff919091166004820152602490fd5b909290916001600160801b03908116158080614048575b15613fa457505050613f11825160ff1690565b60ff81166010811015613f63575050613f4b613f43613f34610e42945160ff1690565b600160ff9091161b61ffff1690565b916005610b80565b90613f5c825461ffff9060e81c1690565b179061346a565b601891935010613f71575050565b613f91613f43613f856010610e42956133fd565b600160ff9182161b1690565b90613f9d825460f81c90565b1790613255565b15918261403d575b5050613fb6575050565b815160ff16806010811015613ffe575050613fe6613f43613fde613f34610e42955160ff1690565b1961ffff1690565b90613ff7825461ffff9060e81c1690565b169061346a565b60189193501061400c575050565b61402a613f43614023613f856010610e42966133fd565b1960ff1690565b90614036825460f81c90565b1690613255565b161590503880613fac565b508183161515613efe565b939293600260015460f81c16611da5576136856140709183611ead565b611072576001600160a01b038181168382161461410557807f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda0291316908516146000146140d457610e42935060001983036141175791506140ce82615079565b91614117565b9192906040600854166140f3576140ed610e429461372c565b92614489565b604051630ecd760560e01b8152600490fd5b60405163e397a99b60e01b8152600490fd5b9190916141226122f1565b61412d816005610b80565b61413690612199565b614141846005610b80565b61414a90612199565b91815161415790600c0b90565b92805161416490600c0b90565b9261416e85612f5d565b61417787612caa565b61418091612b0a565b9561418a85612f5d565b9061419490612caa565b61419d91612b41565b906141a78761393e565b6141b1819361393e565b9687936141bd91614424565b976141c89197613ad4565b9787896001546141d79061228e565b906141e191613782565b906141eb916137be565b6141f690600161379f565b600154614202906122e2565b9061420c91613782565b90614216916137be565b6142219060016137d6565b61422b9185613504565b6142359187613504565b60009384811215614400576020600854166143ee5761425390612f4c565b7f0000000000000000000000000000000000000000000000000000000000000001116143dc5761428561368582612cdf565b6143ca57835460015466038d7ea4c68000906142d3906001600160681b036142af888284166137be565b6001600160401b03906142c49087831661281d565b9560401c169160681c1661229a565b0490801515918261439c575b505061438a5783905b6001600160681b0392808416614343575b505050811661430757505050565b61393961432760008051602061515f8339815191529261270e8554610da0565b6040519081526001600160a01b03909416939081906020820190565b61437f61436360008051602061515f8339815191529261270e8654610da0565b6040519081526001600160a01b03909316929081906020820190565b0390a38238806142f9565b60405163e012b19360e01b8152600490fd5b671bc16d674ec800009250906143bd670de0b6b3a76400006143c29361229a565b612807565b1138806142df565b604051630a62fbdb60e11b8152600490fd5b604051637139da2360e11b8152600490fd5b604051634f49eff560e11b8152600490fd5b506010600854166144125783906142e8565b60405163192efc2360e21b8152600490fd5b919082600c0b81600c0b818113613b43576000136144475750613af89192613a92565b60001261445857613b189192613a92565b61446190612f26565b6001600160681b03928316921690565b6001600160801b039182169116818110612282570390565b9192909261449f612e7f82613e62866006610b80565b6144b1612e7f83613e62886006610b80565b6144bb8483614471565b916144c68583613cf1565b926144da81613e8887613e628b6006610b80565b6144ed84613e8887613e628c6006610b80565b6144f6856120ec565b91614502835160ff1690565b61450e60ff82166132b4565b614592575061453d94939291614537916145278a6121e4565b6145308b6121e4565b838a613ee7565b87613ee7565b61454961368584612cdf565b6143ca576040516001600160a01b0391821694821693909116917f29db89d45e1a802b4d55e202984fce9faf1d30aedf86503ff1ea0ed9ebb6420191908190613eb39082613d61565b60405163460d2b4f60e01b815260ff919091166004820152602490fd5b939293600460015460f81c16611da5576136856145cc9183611ead565b611072576001600160a01b038481167f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029139091160361462357610e429350600019830361465457915061461d82615079565b91614654565b9192906080600854166146425761463c610e429461372c565b926148c1565b604051631e16772b60e01b8152600490fd5b90916138ac926146626122f1565b614670613847846005610b80565b6146ca61467e8251600c0b90565b61469361468a82612f5d565b612c5987612caa565b926138b36146aa6146a38661393e565b8094614424565b6146bf613895836138a760019e959e5461228e565b6138906001546122e2565b60008112156147e0576002600854166147ce576146e690612f4c565b7f0000000000000000000000000000000000000000000000000000000000000001116143dc5761471861368584612cdf565b6143ca57671bc16d674ec8000061472d612949565b1161438a575b61475e82827f000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda02913614819565b6040519182526001600160a01b0392831692169082907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90602090a36001600160681b0382166147ac575050565b60008051602061515f83398151915261393961392960009461270e8654610da0565b604051635088313560e11b8152600490fd5b5060016008541615614733576040516325964bab60e11b8152600490fd5b6001600160a01b039091168152602081019190915260400190565b6001600160a01b03169291833b156106ea5761485390604051809581809563a9059cbb60e01b8252600098899687968793600484016147fe565b03925af180156148b4575b6148a4575b503d9050801561489957602014614878575080fd5b90602081803e515b1561488757565b60405163cefaffeb60e01b8152600490fd5b509050600019614880565b6148ad91611f01565b3882614863565b6148bc611fb0565b61485e565b919290926148ce836121e4565b6148e0612e7f82613e62866006610b80565b6148ea8382614471565b906149126148f9846002610b80565b61490c866149078354610b97565b614471565b90613d0e565b61492582613e8885613e62896006610b80565b61492e836120ec565b805160ff1661493c81613286565b61499757509061494d929186613ee7565b61495961368584612cdf565b6143ca577fd6d480d5b3068db003533b170d67561494d72e3bf9fa40a266471351ebba9e1690613eb390613e936001600160801b0385168783614819565b604051630db276b560e01b815260ff919091166004820152602490fd5b91908110156149c45760051b0190565b612ff361302a565b35610b7d816106d9565b906040516149e5608082611f01565b915463ffffffff81168352602081811c6001600160401b031690840152606081811c6001600160801b0316604085015260e09190911c90830152565b60019063ffffffff8091169081146122d6570190565b9291909260016008815460f81c16611da5575a94614a536122f1565b60005b848110614b4d57505050614af890614af1614ad2613db6614a7c610e4297985a906125cd565b614acb614ab9614a95614a90886007610b80565b6149d6565b98612448614aaf614aaa8c5163ffffffff1690565b614a21565b63ffffffff168b52565b6135d560208a01916124578351610da0565b489061229a565b614ae46040860191613de18351610b97565b6001600160801b03169052565b6007610b80565b815160208084015160408501516060958601516001600160e01b031960e09190911b16600160601b600160e01b039190961b1663ffffffff909316600160201b600160601b039190921b161717919091179055565b80614b6b614b65614b60869489876149b4565b6149cc565b86614b71565b01614a56565b90614b7b81613063565b9192909215614efa57614b92613847826005610b80565b92614b9e8451600c0b90565b614ba781612f5d565b606086015161ffff16608087015160ff1695614bc1611f31565b50600096875b60ff7f00000000000000000000000000000000000000000000000000000000000000051660ff821610614d7c5750505050614c3b614c35612ec9856143bd60018060401b037f00000000000000000000000000000000000000000000000000000000000f424016809a61229a565b82612b41565b9160008312614d73575b614c4e8361393e565b9687614c5a9187613504565b614c65856005610b80565b6000614c709161346a565b86614c7c866005610b80565b6000614c8791613255565b614c9091613ad4565b600154614c9c9061228e565b90614ca691613782565b614cb190600161379f565b600154614cbd906122e2565b90614cc7916137be565b614cd29060016137d6565b614cdb91612b0a565b614ce490614f35565b92614cef9184613309565b6040805193845260208401919091526001600160a01b039182169485939216917f1547a878dc89ad3c367b6338b4be6a65a5dd74fb77ae044da1e8747ef1f4f62f9190a380600c0b600012614d42575050565b60008051602061515f833981519152613939613929600093614d6d614d678654610da0565b91614f0c565b9061281d565b60009250614c45565b614d8782828661340f565b614d9a575b60010160ff16925b92614bc7565b878b614da583611fbd565b60c08101516001600160401b0390614dbc90610da0565b1615614eeb57602081015183906001600160a01b03169c8d80600681614de28683610b80565b90614dec91610b80565b614df590610ba3565b94614dff91610b80565b90614e0991610b80565b6000614e1491613d0e565b614e1f906002610b80565b828154614e2b90610b97565b90614e3591614471565b614e3e91613d0e565b614e4b60ff871689613041565b516060840151614e5a90610da0565b614e6d916001600160801b038516613309565b9260c00151614e7b90610da0565b614e8490610da0565b614e8e90846132cb565b614e97916125c1565b604080516001600160801b0393909316835260208301939093529c6001600160a01b039081169481169316917f9850ab1af75177e4a9201c65a2cf7976d5d28e40ef63494b44366f86b2f9412e91a4614d8c565b50505060010160ff1692614d94565b604051636ef5bcdd60e11b8152600490fd5b600081600c0b12614f23576001600160681b031690565b60405163363b64b760e11b8152600490fd5b60008112614f235790565b610b7d91614f50614fc9926120ec565b6040810151614f67906001600160a01b03166129d7565b60c08201519091906001600160401b0390811680614ff0575b5050614fc3612ebe6060614fbb6143bd95966136607f0000000000000000000000003e6d1cca8eee6d02f1f578b613374eb53e6823b46129d7565b930151610da0565b9061229a565b7f00000000000000000000000000000000000000000000000000000000000f424090612807565b6060614fbb614fc3936150556143bd97612ebe95615044670de0b6b3a764000094828693841061506c575b8303167f0000000000000000000000000000000000000000000000000853a0d2313c000061229a565b0480841061505f575b83039061229a565b0495505050614f80565b615067612255565b61504d565b615074612255565b61501b565b61509c615084612170565b61083964ffffffffff918260015460d01c169061226c565b506001600160a01b03909116600090815260056020526040812054600c0b9190808313156150d15750614d6d610b7d92614f0c565b91505090565b6150e2615084612170565b6001600160a01b03909216600090815260056020526040812054600c0b929150808312156150d15750614d6d61511a610b7d93612f26565b614f0c565b50600036818037808036817f0000000000000000000000000d4bd55a755134950027ce1f43190a354e648e205af43d82803e1561515a573d90f35b3d90fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc98c7730ba19013824f711a9ab74801459b27e6ff7685cb924587c89aeda53aca26469706673582212208b5b38d54ee250e2991d5501396c297bd513e3288a62f62831cc572d55212c0364736f6c634300080f0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"libraries":{},"optimizer":{"details":{"yulDetails":{"optimizerSteps":"dhfoDgvulfnTUtnIf [xa[r]scLM cCTUtTOntnfDIul Lcul Vcul [j] Tpeul xa[rul] xa[r]cL gvif CTUca[r]LsTOtfDnca[r]Iulc] jmul[jul] VcTOcul jmul"}},"enabled":true,"runs":1},"outputSelection":{"*":{"":["*"],"*":["*"]}},"viaIR":true},"optimization_runs":1,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"v0.8.15+commit.e14f2714","is_verified_via_verifier_alliance":false,"verified_at":"2026-08-26T14:47:08.129824Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6103a0806040523462000a915762005cf3803803809162000021828562000aac565b8339602082828101031262000a915781516001600160401b03811162000a91576102a0818401838501031262000a915760405192620000636102a08562000aac565b6200007082820162000ad0565b84526200008260208383010162000ad0565b60208501526200009760408383010162000ad0565b6040850152620000ac60608383010162000ad0565b6060850152620000c160808383010162000ad0565b6080850152620000d660a08383010162000ae5565b60a0850152620000eb60c08383010162000ae5565b60c08501526200010060e08383010162000ae5565b60e0850152620001166101008383010162000ae5565b6101008501526200012d6101208383010162000ae5565b610120850152620001446101408383010162000ae5565b6101408501526200015b6101608383010162000ae5565b610160850152620001726101808383010162000ae5565b610180850152620001896101a08383010162000ae5565b6101a0850152620001a06101c08383010162000ae5565b6101c0850152620001b76101e08383010162000ae5565b6101e0850152620001ce6102008383010162000ae5565b610200850152620001e56102208383010162000afa565b610220850152620001fc6102408383010162000afa565b610240850152620002136102608383010162000afa565b6102608501528082016102800151926001600160401b03841162000a9157808201601f858585010101121562000a9157818301840151916001600160401b03831162000a9657604051946200026f60208560051b018762000aac565b8386526020860194838301602060e08702848487010101011162000a9157828101820160200195915b602060e08702828487010101018710620009d35761028089018890526040808a0151905163313ce56760e01b81528a91602090829060049082906001600160a01b03165afa908115620008245760009162000991575b50601260ff82161162000902576101a0820151670de0b6b3a76400006001600160401b03909116116200097f57601861028083015151116200096d576102208201516001600160681b0316156200095b57606082015160405163313ce56760e01b815290602090829060049082906001600160a01b03165afa908115620008245760009162000914575b5060ff6008911603620009025781516001600160a01b0390811660809081526020840151821660a0526040840151821660c0526060840151821660e05283015116610100526101a08201516001600160401b039081166102205261032082905260ff909116600a0a81166102408190526101c083015190911661026052620f42401162000902576102408051620f42409004610360526102208201516001600160681b039081166102c0526101e0808401516001600160401b039081166102809081526102008087015183166102a0529486015184166102e0526102608601519093166103005260a0850151811661012090815260c08601516301e13380908316819004831661014090815260e088015184168290048416610160908152610100808a015186168490048616610180908152948a015186166101a05291890151851683900485166101c0528801518416829004841690945290860151821604169092528201515160ff166103405251604051630e085c5b60e31b81529190602090839060049082906001600160a01b03165afa9182156200082457600092620008b8575b50610280015190604051809263ba15b9d160e01b82526024820160206004840152815180915260206044840192019060005b8181106200083057506020949284900392849250600091506001600160a01b03165af19081156200082457600091620007df575b50610380526040516151d462000b1f82396080518181816107c601528181610f81015281816116e80152611b6f015260a051818181610a2a0152611087015260c0518181816109d001528181611667015281816118a901528181611bd801528181611c900152818161273601528181612bcc0152818161369a0152818161380a0152818161408a015281816145dd015261473a015260e051818181611df101528181612d41015281816130d80152614f970152610100518181816110c7015261512c01526101205181818161161501526126020152610140518181816111b00152818161263e01526126a90152610160518181816112e301526126d50152610180518181816114670152818161266501526127c301526101a0518181816113ef015261285801526101c051818181610c380152818161289401526128ff01526101e051818181610b35015261292501526102005181818161125f01526128bb01526102205181818161093c0152615020015261024051818181610f0101528181612d7001528181613112015281816132e401528181614c0e0152614fcb0152610260518181816116a7015261357701526102805181818161087a015261249701526102a0518181816114d9015261241f01526102c05181818161142b015261239101526102e051818181610cb20152818161425501526146e8015261030051818181610d2d0152611d7e01526103205181610cf00152610340518181816115d8015281816120ff01528181612da7015281816130870152614bcb0152610360518161359e015261038051818181611b140152611fe801526151d490f35b6020813d6020116200081b575b81620007fb6020938362000aac565b81010312620008175762000810915062000ad0565b8162000582565b5080fd5b3d9150620007ec565b6040513d6000823e3d90fd5b825180516001600160a01b0390811686526020828101519091168187015260408083015160ff16908701526060808301516001600160401b039081169188019190915260808084015182169088015260a0808401519091169087015260c0918201516001600160801b03169186019190915287955060e090940193909201916001016200054e565b90916020823d602011620008f9575b81620008d66020938362000aac565b81010312620008f65750620008ee6102809162000ad0565b91906200051c565b80fd5b3d9150620008c7565b604051630456c65960e51b8152600490fd5b906020823d60201162000952575b81620009316020938362000aac565b81010312620008f6575060ff6200094a60089262000b0f565b915062000378565b3d915062000922565b604051636e77247560e01b8152600490fd5b60405163df8153c760e01b8152600490fd5b6040516324dc918f60e11b8152600490fd5b906020823d602011620009ca575b81620009ae6020938362000aac565b81010312620008f65750620009c39062000b0f565b82620002ee565b3d91506200099f565b60e087868601031262000a915760405192620009f160e08562000aac565b620009fc8862000ad0565b845262000a0c6020890162000ad0565b602085015262000a1f6040890162000b0f565b604085015262000a326060890162000ae5565b606085015262000a456080890162000ae5565b608085015262000a5860a0890162000ae5565b60a085015260c0880151936001600160801b038516850362000a9157602060e09282829760c08695015281520198019793505062000298565b600080fd5b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b0382119082101762000a9657604052565b51906001600160a01b038216820362000a9157565b51906001600160401b038216820362000a9157565b51906001600160681b038216820362000a9157565b519060ff8216820362000a915756fe60806040526004361015610018575b61001661511f565b005b60003560e01c8063042e02cf146106d05780630546e6ec146106c75780630902f1ac146106be5780630bc47ad1146106b55780630c340a24146106ac57806318160ddd146106a3578063189bb2f11461069a5780631c9f7fb9146106915780631f5954bd14610688578063214435621461067f57806323b872dd1461067657806324a3d6221461066d578063264413181461066457806329c5a1a01461065b5780632a48cf12146106525780632b92a07d146106495780632d05670b146106405780632e04b8e714610637578063300e6beb1461062e578063313ce5671461062557806332176c491461061c578063374c49b41461061357806338aa813f1461060a5780633b3bec2e1461060157806341976e09146105f85780634232cd63146105ef578063439e2e45146105e657806344c1e5eb146105dd57806344c35d07146105d457806344ff241d146105cb5780634a95a76a146105c257806350a1efea146105b957806359e017bd146105b05780635a94b8d1146105a757806367800b5f1461059e5780636f678cce1461059557806370a082311461058c5780637914acc7146105835780637ac88ed11461057a5780637eb7113114610571578063804de71f146105685780638285ef401461055f5780638a5704df146105565780638d5d814c1461054d57806390323177146105445780639241a5611461053b5780639364e18a1461053257806394920cca146105295780639545e4de146105205780639ae3890c146105175780639ea99a5a1461050e5780639fa83b5a146105055780639ff567f8146104fc578063a1654379146104f3578063a1a1ef43146104ea578063a46fe83b146104e1578063a5b4ff79146104d8578063a9059cbb146104cf578063aba7f15e146104c6578063ad14777c146104bd578063b2a7a721146104b4578063bfe69c8d146104ab578063c04a5b06146104a2578063c1ee2c1814610499578063c3b35a7e14610490578063c3cecfd214610487578063c55dae631461047e578063c5fa15cf14610475578063c82643b41461046c578063c8c7fe6b14610463578063cde680411461045a578063cdfadab614610451578063ce26a7b014610448578063d8e5f6111461043f578063d955759d14610436578063dc4abafd1461042d578063e1066c9014610424578063e30ca4041461041b578063e372f03a14610412578063e478795d14610409578063e4e6e77914610400578063e719dc74146103f7578063e7dad6bd146103ee578063f2b9fdb8146103e5578063f3fef3a3146103dc5763fddc530f0361000e576103d7611e89565b61000e565b506103d7611e54565b506103d7611e20565b506103d7611dda565b506103d7611db7565b506103d7611c2e565b506103d7611b43565b506103d7611afd565b506103d7611ad9565b506103d7611ab2565b506103d7611a3f565b506103d7611a20565b506103d76119f9565b506103d76119d5565b506103d76119ba565b506103d761199e565b506103d7611975565b506103d7611946565b506103d76118d8565b506103d7611892565b506103d761182d565b506103d7611809565b506103d76117e3565b506103d76117bc565b506103d7611796565b506103d761176f565b506103d76116ca565b506103d761168e565b506103d7611638565b506103d76115fc565b506103d76115bd565b506103d7611596565b506103d7611555565b506103d761152d565b506103d76114fc565b506103d76114c0565b506103d76114a5565b506103d761148a565b506103d761144e565b506103d7611412565b506103d76113d6565b506103d76113b1565b506103d761138a565b506103d7611367565b506103d7611306565b506103d76112ca565b506103d76112ae565b506103d7611282565b506103d7611246565b506103d761121e565b506103d76111fa565b506103d76111d3565b506103d7611197565b506103d7611141565b506103d761111d565b506103d76110f6565b506103d76110b0565b506103d7610f31565b506103d7610ee8565b506103d7610ec4565b506103d7610ea1565b506103d7610e79565b506103d7610e44565b506103d7610d78565b506103d7610d50565b506103d7610d14565b506103d7610cd5565b506103d7610c99565b506103d7610c5b565b506103d7610c1f565b506103d7610bca565b506103d7610b1c565b506103d7610ae5565b506103d7610a90565b506103d7610a13565b506103d76109b0565b506103d761095f565b506103d7610923565b506103d761089d565b506103d7610861565b506103d76107f5565b506103d76107af565b506103d7610776565b506103d7610752565b506103d761072e565b506103d76106ef565b6001600160a01b038116036106ea57565b600080fd5b50346106ea5760203660031901126106ea576020610717600435610712816106d9565b613063565b50506040519015158152f35b60009103126106ea57565b50346106ea5760003660031901126106ea5760206080600854161515604051908152f35b50346106ea5760003660031901126106ea57602061076e612b7a565b604051908152f35b50346106ea5760003660031901126106ea5760206001805460f81c161515604051908152f35b6001600160a01b03909116815260200190565b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760003660031901126106ea57602066038d7ea4c6800061085861081c612170565b61083f6001549161083964ffffffffff91828560d01c169061226c565b16612520565b506001600160401b0316906001600160681b031661229a565b04604051908152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576000806003193601126109205760015464ffffffffff8160d01c1661090f5764ffffffffff60d01b6108d3612170565b64ffffffffff60d01b1990921660d09290921b161760015580546001600160801b0319166e038d7ea4c6800000038d7ea4c68000178155604051f35b60405162dc149f60e41b8152600490fd5b80fd5b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea5760206001600854161515604051908152f35b908160609103126106ea578035610999816106d9565b91604060208301356109aa816106d9565b92013590565b50346106ea576109f66109c4366004610983565b91906109ce613752565b7f00000000000000000000000000000000000000000000000000000000000000009133614053565b600060008051602061517f83398151915255602060405160018152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b91908260809103126106ea578135610a70816106d9565b916020810135610a7f816106d9565b91606060408301356109aa816106d9565b50346106ea57610ab6610aa4366004610a59565b92610ab0929192613752565b336145af565b600060008051602061517f83398151915255005b908160209103126106ea573562ffffff811681036106ea5790565b50346106ea576020610b12610afb366004610aca565b60085460601c600162ffffff8093161b1616151590565b6040519015158152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b91908260409103126106ea5760208235610b71816106d9565b920135610b7d816106d9565b90565b9060018060a01b0316600052602052604060002090565b6001600160801b031690565b546001600160801b031690565b6001600160801b0391821681529116602082015260400190565b50346106ea57610c1b610bff610be1366004610b58565b6001600160a01b039091166000908152600660205260409020610b80565b54604051918291608081901c906001600160801b031683610bb0565b0390f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760203660031901126106ea57600435610c79816106d9565b60018060a01b031660005260046020526020604060002054604051908152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760203660031901126106ea57602061076e600435610d73816106d9565b6150d7565b50346106ea5760203660031901126106ea576020610b12600435610d9b816106d9565b612cdf565b6001600160401b031690565b610e429092919260e08061010083019560ff815116845260018060a01b03806020830151166020860152604082015116604085015260018060401b036060820151166060850152610e0c6080820151608086019060018060401b03169052565b60a0818101516001600160401b03169085015260c0818101516001600160401b03169085015201516001600160801b0316910152565b565b50346106ea5760203660031901126106ea57610c1b610e6d600435610e68816106d9565b6120ec565b60405191829182610dac565b50346106ea5760203660031901126106ea57602061076e600435610e9c816106d9565b6129d7565b50346106ea57610ab6610eb5366004610983565b91610ebe613752565b3361366a565b50346106ea57610ab6610ed8366004610983565b91610ee1613752565b3333614053565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b359081151582036106ea57565b50346106ea5760a03660031901126106ea57610f4d6004610f24565b610f576024610f24565b610f616044610f24565b91610f6c6064610f24565b92610f776084610f24565b60018060a01b03807f0000000000000000000000000000000000000000000000000000000000000000163314159081611083575b50611072577f3be39979091ae7ca962aa1c44e645f2df3c221b79f324afa5f44aedc8d2f690d9461106d92611038610ff56000610fe788613278565b9060ff8080931691161b1690565b6110036001610fe78a613278565b176110126002610fe785613278565b176110216003610fe786613278565b176110306004610fe787613278565b176001613255565b6040519586958693909594919260809360a0860197151586521515602086015215156040850152151560608401521515910152565b0390a1005b6040516282b42960e81b8152600490fd5b90507f00000000000000000000000000000000000000000000000000000000000000001633141538610fab565b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760003660031901126106ea57602062ffffff60085460601c16604051908152f35b50346106ea5760003660031901126106ea576020604051671bc16d674ec800008152f35b50346106ea5760203660031901126106ea5760043561115f816106d9565b6001600160a01b031660009081526002602052604090819020549051908190610c1b90608081901c906001600160801b031683610bb0565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea576020600460015460f81c161515604051908152f35b50346106ea5760003660031901126106ea5760206040600854161515604051908152f35b50346106ea5760203660031901126106ea57602061076e600435611241816106d9565b615079565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760403660031901126106ea57602061076e6004356112a5816106d9565b60243590614f40565b50346106ea5760003660031901126106ea57602061076e612949565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea57602066038d7ea4c6800061085861132d612170565b61134a6001549161083964ffffffffff91828560d01c169061226c565b6001600160401b03169160681c6001600160681b0316905061229a565b50346106ea5760003660031901126106ea57602060088054161515604051908152f35b50346106ea5760003660031901126106ea576020600860015460f81c161515604051908152f35b50346106ea57610ab66113c5366004610a59565b926113d1929192613752565b61366a565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576020610b126114a0366004610aca565b6132b4565b50346106ea576020610b126114bb366004610aca565b61329d565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760203660031901126106ea57602061151b600435612842565b6040516001600160401b039091168152f35b50346106ea5760203660031901126106ea57602061076e600435611550816106d9565b612a82565b50346106ea57602060ff61158a61156d366004610b58565b6001600160a01b0390911660009081526003855260409020610b80565b54166040519015158152f35b50346106ea5760003660031901126106ea576020600260015460f81c161515604051908152f35b50346106ea5760003660031901126106ea57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760403660031901126106ea576109f6600435611659816106d9565b611661613752565b602435907f0000000000000000000000000000000000000000000000000000000000000000903333614053565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576116db366004610983565b91906001600160a01b03907f000000000000000000000000000000000000000000000000000000000000000082163303611072571691823b156106ea5761173c926000928360405180968195829463095ea7b360e01b8452600484016147fe565b03925af18015611762575b61174d57005b8061175c600061001693611f01565b80610723565b61176a611fb0565b611747565b50346106ea5760003660031901126106ea57602062ffffff60085460181c16604051908152f35b50346106ea5760203660031901126106ea576100166004356117b7816106d9565b6121e4565b50346106ea5760003660031901126106ea57602062ffffff60085460301c16604051908152f35b50346106ea57610ab66117f7366004610a59565b92611803929192613752565b33614053565b50346106ea57610ab661181d366004610983565b91611826613752565b33336145af565b50346106ea5760403660031901126106ea5760043561184b816106d9565b602435906001600160401b03908183116106ea57366023840112156106ea5782600401359182116106ea573660248360051b850101116106ea576024610016930190614a37565b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760203660031901126106ea576004356118f6816106d9565b60018060a01b0316600052600760205260806040600020546040519063ffffffff8116825260018060401b038160201c166020830152600180841b038160601c16604083015260e01c6060820152f35b50346106ea5760003660031901126106ea5760206010600854161515604051908152f35b60ff8116036106ea57565b50346106ea5760203660031901126106ea57610c1b610e6d6004356119998161196a565b611fbd565b50346106ea576020610b126119b4366004610b58565b90611ead565b50346106ea576020610b126119d0366004610aca565b613286565b50346106ea5760003660031901126106ea5760206002600854161515604051908152f35b50346106ea5760003660031901126106ea576020601060015460f81c161515604051908152f35b50346106ea5760203660031901126106ea57602061151b6004356125d8565b50346106ea5760203660031901126106ea57600435611a5d816106d9565b60018060a01b0316600052600560205260a06040600020546040519080600c0b825260018060401b03808260681c1660208401528160a81c16604083015261ffff8160e81c16606083015260f81c6080820152f35b50346106ea5760003660031901126106ea57602062ffffff60085460481c16604051908152f35b50346106ea5760003660031901126106ea57602062ffffff60085416604051908152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760403660031901126106ea57600435611b61816106d9565b602435906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116330361107257611b9e612b7a565b60008112908115611c1c575b50611c0a5781611bfc847fec4431f2ba1a9382f6b0c4352b888cba6f7db91667d9f776abe5ad8ddc5401b6947f0000000000000000000000000000000000000000000000000000000000000000614819565b6040519384521691602090a2005b60405163128bd24d60e31b8152600490fd5b611c269150614f35565b831138611baa565b50346106ea5760803660031901126106ea57600435611c4c816106d9565b60643590611c59826106d9565b611c61613752565b601060015460f81c16611da557611c76612b7a565b60008112159081611d7a575b50611d6857611cb4604435337f0000000000000000000000000000000000000000000000000000000000000000613b50565b90611cbf8282614f40565b926024358410611d5657611cd282612a82565b8411611c0a577ff891b2a411b0e66a5f0a6ff1368670fefa287a13f541eb633a386a1a9cc7046b91611d19611d3c92611d12611d0d8861372c565b610b97565b9083614819565b6040805194855260208501959095526001600160a01b0316933393918291820190565b0390a3610016600060008051602061517f83398151915255565b60405163fa6ad35560e01b8152600490fd5b604051631d99ddbf60e01b8152600490fd5b90507f0000000000000000000000000000000000000000000000000000000000000000111538611c82565b6040516313d0ff5960e31b8152600490fd5b50346106ea5760003660031901126106ea57602080600854161515604051908152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760403660031901126106ea57610ab6600435611e41816106d9565b611e49613752565b60243590333361366a565b50346106ea5760403660031901126106ea57610ab6600435611e75816106d9565b611e7d613752565b602435903333336145af565b50346106ea5760003660031901126106ea5760206004600854161515604051908152f35b6001600160a01b03808316911690811491908215611eca57505090565b60ff925090611ee59160005260036020526040600020610b80565b541690565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017611f2457604052565b611f2c611eea565b604052565b60405190611f4161010083611f01565b8160e06000918281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b5190610e428261196a565b5190610e42826106d9565b51906001600160401b03821682036106ea57565b51906001600160801b03821682036106ea57565b506040513d6000823e3d90fd5b611fc5611f31565b5060405163c8c7fe6b60e01b815260ff91909116600482015261010080826024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9182156120df575b60009261202657505090565b90918282813d83116120d8575b61203d8183611f01565b81010312610920575060e06120d0916120596040519485611f01565b61206281611f72565b845261207060208201611f7d565b602085015261208160408201611f7d565b604085015261209260608201611f88565b60608501526120a360808201611f88565b60808501526120b460a08201611f88565b60a08501526120c560c08201611f88565b60c085015201611f9c565b60e082015290565b503d612033565b6120e7611fb0565b61201a565b906120f5611f31565b5060009060ff92837f000000000000000000000000000000000000000000000000000000000000000016925b838582161061213c57604051633640530560e01b8152600490fd5b61214581611fbd565b60208101516001600160a01b0384811691161461216757506001018416612121565b93505050915090565b600160281b4210156121875764ffffffffff421690565b604051633d32ffdb60e01b8152600490fd5b906040516121a860a082611f01565b608081935480600c0b835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c910152565b610e42906121f06122f1565b60018060a01b038116600052600560205260406000206040519061221560a083611f01565b549182600c0b9283835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c6080830152613504565b50634e487b7160e01b600052601160045260246000fd5b64ffffffffff9182169116818110612282570390565b61228a612255565b0390565b6001600160681b031690565b80600019048211811515166122ad570290565b6122b5612255565b0290565b6001600160401b03918216919081169082900381116122d6570190565b6122de612255565b0190565b60681c6001600160681b031690565b6122f9612170565b61232361231961231360015464ffffffffff9060d01c1690565b8361226c565b64ffffffffff1690565b908161232d575050565b8161238461233d610e4294612520565b60008054600160401b600160801b03191660409290921b600160401b600160801b0316919091178155919082546001600160401b0319166001600160401b03909116178255565b61238f60015461228e565b7f000000000000000000000000000000000000000000000000000000000000000092906001600160681b031683811015612484575b506123d86123d36001546122e2565b61228e565b9283101561240c575b50506001805464ffffffffff60d01b191660d09390931b64ffffffffff60d01b169290921790915550565b61244d61244861247c9461244361245c947f000000000000000000000000000000000000000000000000000000000000000061229a565b6132de565b6124fa565b825460c01c6122b9565b6122b9565b81546001600160c01b031660c09190911b6001600160c01b031916179055565b3880806123e1565b6124ce6124bb6124486124f493612443867f000000000000000000000000000000000000000000000000000000000000000061229a565b845460801c6001600160401b03166122b9565b8354600160801b600160c01b03191660809190911b600160801b600160c01b0316178355565b386123c4565b6001600160401b039081811161250e571690565b6040516372a1cb5160e11b8152600490fd5b6000546001600160401b03604082901c81169392918116919081612545575b50509190565b8161259861259261257297946125a46125aa9761259e8761257961259e9961256b612949565b9e8f6125d8565b169d612842565b169b612598612592670de0b6b3a7640000998a9361229a565b8461229a565b046124fa565b906122b9565b9861229a565b91388061253f565b908160209103126106ea575190565b811981116122d6570190565b818110612282570390565b6125e360015461228e565b6001600160681b038116156127e9578115806127c0575b6126ff575b507f00000000000000000000000000000000000000000000000000000000000000008082116126895750612448670de0b6b3a7640000612662610b7d937f000000000000000000000000000000000000000000000000000000000000000061229a565b047f00000000000000000000000000000000000000000000000000000000000000006125c1565b610b7d916126f96126d3836126cd670de0b6b3a7640000612662612448977f000000000000000000000000000000000000000000000000000000000000000061229a565b936125cd565b7f00000000000000000000000000000000000000000000000000000000000000006132cb565b906125c1565b6127139061270e600054610da0565b61281d565b6040516370a0823160e01b81529060208280612732306004830161079c565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9182156127b3575b600092612783575b50101561277d57386125ff565b50600090565b6127a591925060203d81116127ac575b61279d8183611f01565b8101906125b2565b9038612770565b503d612793565b6127bb611fb0565b612768565b507f000000000000000000000000000000000000000000000000000000000000000015156125fa565b5050600090565b50634e487b7160e01b600052601260045260246000fd5b8115612811570490565b6128196127f0565b0490565b66038d7ea4c6800091612819916001600160401b0316906001600160681b031661229a565b60015460681c6001600160681b03161561277d577f00000000000000000000000000000000000000000000000000000000000000008082116128df5750612448670de0b6b3a76400006128b8610b7d937f000000000000000000000000000000000000000000000000000000000000000061229a565b047f00000000000000000000000000000000000000000000000000000000000000006125c1565b610b7d916126f9612923836126cd670de0b6b3a76400006128b8612448977f000000000000000000000000000000000000000000000000000000000000000061229a565b7f00000000000000000000000000000000000000000000000000000000000000006132cb565b60005460015466038d7ea4c680009061298b906001600160681b036001600160401b038461297b82881684861661229a565b049560401c169160681c1661229a565b0481612998575050600090565b670de0b6b3a76400009080600019048211811515166129b657020490565b6129be612255565b020490565b51906001600160501b03821682036106ea57565b604051633fabe5a360e21b81529060a090829060049082906001600160a01b03165afa908115612a75575b600091612a29575b506000811315612a175790565b60405163fd1ee34960e01b8152600490fd5b9060a0823d8211612a6d575b81612a4260a09383611f01565b810103126109205750612a54816129c3565b50612a666080602083015192016129c3565b5038612a0a565b3d9150612a35565b612a7d611fb0565b612a02565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa918215612afd575b600092612add575b506000908152600260205260409020546001600160801b031690818110612282570390565b612af691925060203d81116127ac5761279d8183611f01565b9038612ab8565b612b05611fb0565b612ab0565b600082128015600160ff1b8401831216612b34575b6001600160ff1b038301821316612282570390565b612b3c612255565b612b1f565b6000811280156001600160ff1b03839003841316612b6d575b600160ff1b8290038312166122d6570190565b612b75612255565b612b5a565b610b7d612b85612170565b612ba8612ba36123196001549364ffffffffff8560d01c169061226c565b612520565b90604051926370a0823160e01b845260208480612bc8306004830161079c565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa938415612c9d575b600094612c65575b5091612c59612c53612c5393612c4c612c5f9666038d7ea4c680009260018060401b0384612c3f8260018060681b03941684861661229a565b0497169160681c1661229a565b0495612caa565b91612caa565b90612b0a565b90612b41565b612c5f93919450612c53612c5393612c4c612c90612c599460203d81116127ac5761279d8183611f01565b9794965050935050612c06565b612ca5611fb0565b612bfe565b6001600160ff1b038111612cbb5790565b60405163e7e828ad60e01b8152600490fd5b60ff6001911660ff81146122d6570190565b612cf4612ced826005610b80565b54600c0b90565b6000918282600c0b1215612f1e57612d1b612d10826005610b80565b5460e81c61ffff1690565b612d39612d33612d2c846005610b80565b5460f81c90565b93612f5d565b612d98612d657f00000000000000000000000000000000000000000000000000000000000000006129d7565b6001600160401b03927f000000000000000000000000000000000000000000000000000000000000000084169190613329565b93612da1611f31565b5060ff927f00000000000000000000000000000000000000000000000000000000000000008416875b8186821610612ddf5750505050505050121590565b612dea84828561340f565b612dfd575b612df890612ccd565b612dca565b9688811215612f1057612e0f88611fbd565b612e26610afb612e20835160ff1690565b60ff1690565b612ee257608081019086612e3a8351610da0565b1615612ed65791612c5f612ec9612ece93612ec3612ebe612eb7612df8988f612e7f612e6a612e84926006610b80565b60208401516001600160a01b03165b90610b80565b610ba3565b90612ea86060612ea0610e9c604085015160018060a01b031690565b920151610da0565b916001600160801b0316613309565b9251610da0565b610da0565b906132cb565b612caa565b979050612def565b505096612df890612ccd565b60200151612f0c906001600160a01b0316604051637050033f60e01b81529182916004830161079c565b0390fd5b505050505050505050600190565b505050600190565b600c0b6001600160671b03198114612f3f575b60000390565b612f47612255565b612f39565b600160ff1b8114612f3f5760000390565b6000600c82900b12612f9d57600054610b7d9166038d7ea4c6800091612f97916001600160401b03909116906001600160681b031661229a565b04612caa565b612fcd612ec9610b7d92612fbe60018060401b0360005460401c1691612f26565b6001600160681b03169061281d565b612f4c565b6020906001600160401b038111612feb575b60051b0190565b612ff3611eea565b612fe4565b9061300282612fd2565b61300f6040519182611f01565b8281528092613020601f1991612fd2565b0190602036910137565b50634e487b7160e01b600052603260045260246000fd5b6020918151811015613056575b60051b010190565b61305e61302a565b61304e565b90613072612ced836005610b80565b916000918284600c0b121561324a5760ff92837f000000000000000000000000000000000000000000000000000000000000000016906130b182612ff8565b906130c0612d10866005610b80565b936130cf612d2c876005610b80565b916131026130fc7f00000000000000000000000000000000000000000000000000000000000000006129d7565b99612f5d565b6001600160401b03939061313b907f00000000000000000000000000000000000000000000000000000000000000008616908c90613329565b96613144611f31565b50825b8a8116888110156132385761315d84838561340f565b613171575b5061316c90612ccd565b613147565b848a929a1215613227576131848a611fbd565b60a08101918c896131958551610da0565b16156132195761321293612ec3612ebe612eb78e87612ea86060613209612c5f9a61320361316c9f9d6131f0612ec99d6131de610e9c6040612e7f95015160018060a01b031690565b6131e8868c613041565b526006610b80565b60208801516001600160a01b0316612e79565b95613041565b51920151610da0565b9890613162565b505050509761316c90612ccd565b505050509450945050935050929190565b50505050949350945050935012929190565b919250508190606090565b80546001600160f81b031660f89290921b6001600160f81b031916919091179055565b60009015610b7d5750600190565b60085460181c600162ffffff8093161b1616151590565b60085460301c600162ffffff8093161b1616151590565b60085460481c600162ffffff8093161b1616151590565b670de0b6b3a7640000916128199161229a565b612807907f00000000000000000000000000000000000000000000000000000000000000009061229a565b906133139161229a565b6001600160401b03909116908115612811570490565b919061333490612caa565b6000808413939082136001600160ff1b038582168482048411166133f0575b600160ff1b956000851291859183168589058312166133e3575b600085129384168289058612166133d6575b0583129116166133c9575b6001600160401b039092169291029082156133bc575b81146000198314166133b0570590565b6133b8612255565b0590565b6133c46127f0565b6133a0565b6133d1612255565b61338a565b6133de612255565b61337f565b6133eb612255565b61336d565b6133f8612255565b613353565b60ff9182169116818110612282570390565b9060ff16916010831060001461342e5750600161ffff921b1616151590565b90506018821061343f575050600090565b600160ff8093600f1901161b1616151590565b6001600160401b039182169116818110612282570390565b805461ffff60e81b191660e89290921b61ffff60e81b16919091179055565b81518154602084015160408501516001600160e81b03199092166001600160681b039093169290921760689290921b600160681b600160a81b03169190911760a89190911b600160a81b600160e81b03161781556060820151610e429260ff91608091906134fb9061ffff168561346a565b01511690613255565b61361390610e42936135178451600c0b90565b600c82900b855260009182918683600c83900b811361362a5761359c6135756135e294613566612ebe6135c3966135606020612ea0612448995460018060401b039060801c1690565b90613452565b906001600160681b031661229a565b7f000000000000000000000000000000000000000000000000000000000000000090612807565b7f000000000000000000000000000000000000000000000000000000000000000090612807565b6135d560408901916124578351610da0565b6001600160401b03169052565b600c0b12613618575461360c9060801c6001600160401b03165b6001600160401b03166020850152565b6005610b80565b613489565b546136259060c01c6135fc565b61360c565b61359c613575613665946136606123d361228e61365a612ebe6135c3996135606020612ea06124489c5460c01c90565b93612f26565b61229a565b6135e2565b92916001805460f81c16611da5576136896136853386611ead565b1590565b611072576001600160a01b038181167f0000000000000000000000000000000000000000000000000000000000000000909116036136fa575060088054166136e957610e429260001983036137ff5791506136e3816150d7565b916137ff565b6040516230dad960e61b8152600490fd5b9060046008949394541661371a57613714610e429461372c565b92613d74565b60405163b4abb28d60e01b8152600490fd5b6001600160801b0390818111613740571690565b60405163762ea71160e11b8152600490fd5b60008051602061517f83398151915260018154146137705760019055565b60405163139b643560e21b8152600490fd5b6001600160681b03918216919081169082900381116122d6570190565b80546001600160681b0319166001600160681b03909216919091179055565b6001600160681b039182169116818110612282570390565b8054600160681b600160d01b03191660689290921b600160681b600160d01b0316919091179055565b61382e6138ac9293827f0000000000000000000000000000000000000000000000000000000000000000613b50565b6138366122f1565b6138b961384c613847866005610b80565b612199565b8051600c0b906138b361387c61387561387061386786612f5d565b612c5f89612caa565b61393e565b8094613ad4565b979061389c6138958a61389060015461228e565b613782565b600161379f565b6138a76001546122e2565b6137be565b60016137d6565b86613504565b6040519081526001600160a01b0393841693849216907fd1cf3d156d5f8f0d50f6c122ed609cec09d35c9b9fb3fff6ea0959134dae424e90602090a36001600160681b038116613907575050565b60008051602061515f83398151915261393961392960009361270e8554610da0565b6040519081529081906020820190565b0390a3565b6000811261396457600054610b7d9161395f916001600160401b03166139ed565b613a63565b6139c161395f610b7d9261398560018060401b0360005460401c1691612f4c565b6139aa826000199266038d7ea4c68000908085048211811515166139e0575b026125c1565b600181106139d3575b82156139c6575b0104613a3d565b612f26565b6139ce6127f0565b6139ba565b6139db612255565b6139b3565b6139e8612255565b6139a4565b90610b7d9166038d7ea4c68000908260001904821183151516613a30575b6001600160401b0316918215613a23575b0204613a3d565b613a2b6127f0565b613a1c565b613a38612255565b613a0b565b6001600160681b0390818111613a51571690565b604051630dc7925560e11b8152600490fd5b6001600160681b03166001600160671b038111613a8057600c0b90565b604051639369ae3560e01b8152600490fd5b600c91820b910b6000821280156001600160671b03198401831216613ac7575b6001600160671b038301821316612282570390565b613acf612255565b613ab2565b91909180600c0b83600c0b818112613b4357600012613b075750613af89192613a92565b6001600160681b031690600090565b600013613b2a57613b189192613a92565b6000916001600160681b039190911690565b613b3390612f26565b6001600160681b03908116921690565b5050509050600090600090565b6040516370a0823160e01b8082529390926020926001600160a01b03169190838580613b7f306004830161079c565b0381865afa948515613cbd575b600095613c9e575b50823b156106ea576040516323b872dd60e01b81526001600160a01b03919091166004820152306024820152604481019190915260008160648183865af18015613c91575b613c7c575b503d8015613c7357602014613bf257600080fd5b816000803e6000515b15613c615781610b7d9460405192839182528180613c1c306004830161079c565b03915afa918215613c54575b600092613c37575b50506125cd565b613c4d9250803d106127ac5761279d8183611f01565b3880613c30565b613c5c611fb0565b613c28565b60405163073d1efd60e51b8152600490fd5b50600019613bfb565b8061175c6000613c8b93611f01565b38613bde565b613c99611fb0565b613bd9565b613cb6919550843d86116127ac5761279d8183611f01565b9338613b94565b613cc5611fb0565b613b8c565b90604051613cd9604082611f01565b91546001600160801b038116835260801c6020830152565b6001600160801b03918216919081169082900381116122d6570190565b80546001600160801b0319166001600160801b03909216919091179055565b90602060018060801b0391613d458382511685613d0e565b0151825490911660809190911b6001600160801b031916179055565b6001600160801b03909116815260200190565b919092613d80826120ec565b805160ff16613d8e8161329d565b613eca5750613d9c856121e4565b6001600160801b0391613dbb90613db69084168686613b50565b61372c565b92613dcf613dca826002610b80565b613cca565b92613df3613de686613de18751610b97565b613cf1565b6001600160801b03168552565b613dfd8451610b97565b90613e0e611d0d60e0860151610b97565b911611613eb857613e93613e8185613eb394613e8d7ffa56f7b24f17183d81894d3ac2ee654e3c26388d17a28dbd9549b8114304e1f497613e8887613e628e613e6e613e67612e7f85613e62856006610b80565b610b80565b9889613cf1565b988995613e7c856002610b80565b613d2d565b6006610b80565b613d0e565b89613ee7565b6040516001600160a01b0391821696821695909116939091829182613d61565b0390a4565b604051637ac7b99d60e11b8152600490fd5b6040516335d1e86560e11b815260ff919091166004820152602490fd5b909290916001600160801b03908116158080614048575b15613fa457505050613f11825160ff1690565b60ff81166010811015613f63575050613f4b613f43613f34610e42945160ff1690565b600160ff9091161b61ffff1690565b916005610b80565b90613f5c825461ffff9060e81c1690565b179061346a565b601891935010613f71575050565b613f91613f43613f856010610e42956133fd565b600160ff9182161b1690565b90613f9d825460f81c90565b1790613255565b15918261403d575b5050613fb6575050565b815160ff16806010811015613ffe575050613fe6613f43613fde613f34610e42955160ff1690565b1961ffff1690565b90613ff7825461ffff9060e81c1690565b169061346a565b60189193501061400c575050565b61402a613f43614023613f856010610e42966133fd565b1960ff1690565b90614036825460f81c90565b1690613255565b161590503880613fac565b508183161515613efe565b939293600260015460f81c16611da5576136856140709183611ead565b611072576001600160a01b038181168382161461410557807f000000000000000000000000000000000000000000000000000000000000000016908516146000146140d457610e42935060001983036141175791506140ce82615079565b91614117565b9192906040600854166140f3576140ed610e429461372c565b92614489565b604051630ecd760560e01b8152600490fd5b60405163e397a99b60e01b8152600490fd5b9190916141226122f1565b61412d816005610b80565b61413690612199565b614141846005610b80565b61414a90612199565b91815161415790600c0b90565b92805161416490600c0b90565b9261416e85612f5d565b61417787612caa565b61418091612b0a565b9561418a85612f5d565b9061419490612caa565b61419d91612b41565b906141a78761393e565b6141b1819361393e565b9687936141bd91614424565b976141c89197613ad4565b9787896001546141d79061228e565b906141e191613782565b906141eb916137be565b6141f690600161379f565b600154614202906122e2565b9061420c91613782565b90614216916137be565b6142219060016137d6565b61422b9185613504565b6142359187613504565b60009384811215614400576020600854166143ee5761425390612f4c565b7f0000000000000000000000000000000000000000000000000000000000000000116143dc5761428561368582612cdf565b6143ca57835460015466038d7ea4c68000906142d3906001600160681b036142af888284166137be565b6001600160401b03906142c49087831661281d565b9560401c169160681c1661229a565b0490801515918261439c575b505061438a5783905b6001600160681b0392808416614343575b505050811661430757505050565b61393961432760008051602061515f8339815191529261270e8554610da0565b6040519081526001600160a01b03909416939081906020820190565b61437f61436360008051602061515f8339815191529261270e8654610da0565b6040519081526001600160a01b03909316929081906020820190565b0390a38238806142f9565b60405163e012b19360e01b8152600490fd5b671bc16d674ec800009250906143bd670de0b6b3a76400006143c29361229a565b612807565b1138806142df565b604051630a62fbdb60e11b8152600490fd5b604051637139da2360e11b8152600490fd5b604051634f49eff560e11b8152600490fd5b506010600854166144125783906142e8565b60405163192efc2360e21b8152600490fd5b919082600c0b81600c0b818113613b43576000136144475750613af89192613a92565b60001261445857613b189192613a92565b61446190612f26565b6001600160681b03928316921690565b6001600160801b039182169116818110612282570390565b9192909261449f612e7f82613e62866006610b80565b6144b1612e7f83613e62886006610b80565b6144bb8483614471565b916144c68583613cf1565b926144da81613e8887613e628b6006610b80565b6144ed84613e8887613e628c6006610b80565b6144f6856120ec565b91614502835160ff1690565b61450e60ff82166132b4565b614592575061453d94939291614537916145278a6121e4565b6145308b6121e4565b838a613ee7565b87613ee7565b61454961368584612cdf565b6143ca576040516001600160a01b0391821694821693909116917f29db89d45e1a802b4d55e202984fce9faf1d30aedf86503ff1ea0ed9ebb6420191908190613eb39082613d61565b60405163460d2b4f60e01b815260ff919091166004820152602490fd5b939293600460015460f81c16611da5576136856145cc9183611ead565b611072576001600160a01b038481167f00000000000000000000000000000000000000000000000000000000000000009091160361462357610e429350600019830361465457915061461d82615079565b91614654565b9192906080600854166146425761463c610e429461372c565b926148c1565b604051631e16772b60e01b8152600490fd5b90916138ac926146626122f1565b614670613847846005610b80565b6146ca61467e8251600c0b90565b61469361468a82612f5d565b612c5987612caa565b926138b36146aa6146a38661393e565b8094614424565b6146bf613895836138a760019e959e5461228e565b6138906001546122e2565b60008112156147e0576002600854166147ce576146e690612f4c565b7f0000000000000000000000000000000000000000000000000000000000000000116143dc5761471861368584612cdf565b6143ca57671bc16d674ec8000061472d612949565b1161438a575b61475e82827f0000000000000000000000000000000000000000000000000000000000000000614819565b6040519182526001600160a01b0392831692169082907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90602090a36001600160681b0382166147ac575050565b60008051602061515f83398151915261393961392960009461270e8654610da0565b604051635088313560e11b8152600490fd5b5060016008541615614733576040516325964bab60e11b8152600490fd5b6001600160a01b039091168152602081019190915260400190565b6001600160a01b03169291833b156106ea5761485390604051809581809563a9059cbb60e01b8252600098899687968793600484016147fe565b03925af180156148b4575b6148a4575b503d9050801561489957602014614878575080fd5b90602081803e515b1561488757565b60405163cefaffeb60e01b8152600490fd5b509050600019614880565b6148ad91611f01565b3882614863565b6148bc611fb0565b61485e565b919290926148ce836121e4565b6148e0612e7f82613e62866006610b80565b6148ea8382614471565b906149126148f9846002610b80565b61490c866149078354610b97565b614471565b90613d0e565b61492582613e8885613e62896006610b80565b61492e836120ec565b805160ff1661493c81613286565b61499757509061494d929186613ee7565b61495961368584612cdf565b6143ca577fd6d480d5b3068db003533b170d67561494d72e3bf9fa40a266471351ebba9e1690613eb390613e936001600160801b0385168783614819565b604051630db276b560e01b815260ff919091166004820152602490fd5b91908110156149c45760051b0190565b612ff361302a565b35610b7d816106d9565b906040516149e5608082611f01565b915463ffffffff81168352602081811c6001600160401b031690840152606081811c6001600160801b0316604085015260e09190911c90830152565b60019063ffffffff8091169081146122d6570190565b9291909260016008815460f81c16611da5575a94614a536122f1565b60005b848110614b4d57505050614af890614af1614ad2613db6614a7c610e4297985a906125cd565b614acb614ab9614a95614a90886007610b80565b6149d6565b98612448614aaf614aaa8c5163ffffffff1690565b614a21565b63ffffffff168b52565b6135d560208a01916124578351610da0565b489061229a565b614ae46040860191613de18351610b97565b6001600160801b03169052565b6007610b80565b815160208084015160408501516060958601516001600160e01b031960e09190911b16600160601b600160e01b039190961b1663ffffffff909316600160201b600160601b039190921b161717919091179055565b80614b6b614b65614b60869489876149b4565b6149cc565b86614b71565b01614a56565b90614b7b81613063565b9192909215614efa57614b92613847826005610b80565b92614b9e8451600c0b90565b614ba781612f5d565b606086015161ffff16608087015160ff1695614bc1611f31565b50600096875b60ff7f00000000000000000000000000000000000000000000000000000000000000001660ff821610614d7c5750505050614c3b614c35612ec9856143bd60018060401b037f000000000000000000000000000000000000000000000000000000000000000016809a61229a565b82612b41565b9160008312614d73575b614c4e8361393e565b9687614c5a9187613504565b614c65856005610b80565b6000614c709161346a565b86614c7c866005610b80565b6000614c8791613255565b614c9091613ad4565b600154614c9c9061228e565b90614ca691613782565b614cb190600161379f565b600154614cbd906122e2565b90614cc7916137be565b614cd29060016137d6565b614cdb91612b0a565b614ce490614f35565b92614cef9184613309565b6040805193845260208401919091526001600160a01b039182169485939216917f1547a878dc89ad3c367b6338b4be6a65a5dd74fb77ae044da1e8747ef1f4f62f9190a380600c0b600012614d42575050565b60008051602061515f833981519152613939613929600093614d6d614d678654610da0565b91614f0c565b9061281d565b60009250614c45565b614d8782828661340f565b614d9a575b60010160ff16925b92614bc7565b878b614da583611fbd565b60c08101516001600160401b0390614dbc90610da0565b1615614eeb57602081015183906001600160a01b03169c8d80600681614de28683610b80565b90614dec91610b80565b614df590610ba3565b94614dff91610b80565b90614e0991610b80565b6000614e1491613d0e565b614e1f906002610b80565b828154614e2b90610b97565b90614e3591614471565b614e3e91613d0e565b614e4b60ff871689613041565b516060840151614e5a90610da0565b614e6d916001600160801b038516613309565b9260c00151614e7b90610da0565b614e8490610da0565b614e8e90846132cb565b614e97916125c1565b604080516001600160801b0393909316835260208301939093529c6001600160a01b039081169481169316917f9850ab1af75177e4a9201c65a2cf7976d5d28e40ef63494b44366f86b2f9412e91a4614d8c565b50505060010160ff1692614d94565b604051636ef5bcdd60e11b8152600490fd5b600081600c0b12614f23576001600160681b031690565b60405163363b64b760e11b8152600490fd5b60008112614f235790565b610b7d91614f50614fc9926120ec565b6040810151614f67906001600160a01b03166129d7565b60c08201519091906001600160401b0390811680614ff0575b5050614fc3612ebe6060614fbb6143bd95966136607f00000000000000000000000000000000000000000000000000000000000000006129d7565b930151610da0565b9061229a565b7f000000000000000000000000000000000000000000000000000000000000000090612807565b6060614fbb614fc3936150556143bd97612ebe95615044670de0b6b3a764000094828693841061506c575b8303167f000000000000000000000000000000000000000000000000000000000000000061229a565b0480841061505f575b83039061229a565b0495505050614f80565b615067612255565b61504d565b615074612255565b61501b565b61509c615084612170565b61083964ffffffffff918260015460d01c169061226c565b506001600160a01b03909116600090815260056020526040812054600c0b9190808313156150d15750614d6d610b7d92614f0c565b91505090565b6150e2615084612170565b6001600160a01b03909216600090815260056020526040812054600c0b929150808312156150d15750614d6d61511a610b7d93612f26565b614f0c565b50600036818037808036817f00000000000000000000000000000000000000000000000000000000000000005af43d82803e1561515a573d90f35b3d90fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc98c7730ba19013824f711a9ab74801459b27e6ff7685cb924587c89aeda53aca26469706673582212208b5b38d54ee250e2991d5501396c297bd513e3288a62f62831cc572d55212c0364736f6c634300080f00330000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cc3e7c85bb0ee4f09380e041fee95a0caedd4a020000000000000000000000003cb4653f3b45f448d9100b118b75a1503281d2ee000000000000000000000000833589fcd6edb6e08f4c7c32d4f71b54bda029130000000000000000000000003e6d1cca8eee6d02f1f578b613374eb53e6823b40000000000000000000000000d4bd55a755134950027ce1f43190a354e648e200000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000007fe5cf2bea00000000000000000000000000000000000000000000000000002c5a79111e26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000000062aff19e92200000000000000000000000000000000000000000000000000031f5c4ed2768000000000000000000000000000000000000000000000000000000354a6ba7a180000000000000000000000000000000000000000000000000000853a0d2313c000000000000000000000000000000000000000000000000000000038d7ea4c6800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000048c2739500000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000050000000000000000000000002ae3f1ec7f1f5012cfeab0185bfc7aa3cf0dec220000000000000000000000000866fc8a76bfc485b8e8c7d543a54bd72f015b1c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000001969368974c05b000000000000000000000000000004200000000000000000000000000000000000006000000000000000000000000e6eb5b9b85cff2c84df3de6e7855bc9e76f034d500000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000000d2f13f7789f00000000000000000000000000000000000000000000000002544faa778090e00000000000000000000000000000c1cba3fcea344f92d9239c08c0568f6f2f0ee4520000000000000000000000001738fcae8d5a6aef39985df31fe60e5dc5e1a7b300000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000cbb7c0000ab88b473b1f5afd9ef808440eed33bf0000000000000000000000008c74b2811d2f1ad65517adb5c65773c1e520ed2f00000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000d2f13f7789f000000000000000000000000000000000000000000000000000000000009502f9000000000000000000000000000236aa50979d5f3de3bd1eeb40e81137f22ab794b0000000000000000000000006d75bfb5a5885f841b132198c9f0be8c872057bf00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000001158e460913d00000","name":"CometWithExtendedAssetList","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":false,"language":"solidity","evm_version":"default","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"contracts/IAssetListFactory.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\nimport \"./CometCore.sol\";\n\n/**\n * @title Compound's Asset List Factory\n * @author Compound\n */\ninterface IAssetListFactory {\n    /**\n     * @notice Create a new asset list\n     * @param assetConfigs The asset configurations\n     * @return assetList The address of the new asset list\n     */\n    function createAssetList(CometCore.AssetConfig[] memory assetConfigs) external returns (address assetList);\n}"},{"file_path":"contracts/IAssetListFactoryHolder.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title Compound's Asset List Factory Holder Interface\n * @author Compound\n */\ninterface IAssetListFactoryHolder {\n    /**\n     * @notice Get the asset list factory\n     * @return assetListFactory The asset list factory address\n     */\n    function assetListFactory() external view returns (address);\n}"},{"file_path":"contracts/CometConfiguration.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title Compound's Comet Configuration Interface\n * @author Compound\n */\ncontract CometConfiguration {\n    struct ExtConfiguration {\n        bytes32 name32;\n        bytes32 symbol32;\n    }\n\n    struct Configuration {\n        address governor;\n        address pauseGuardian;\n        address baseToken;\n        address baseTokenPriceFeed;\n        address extensionDelegate;\n\n        uint64 supplyKink;\n        uint64 supplyPerYearInterestRateSlopeLow;\n        uint64 supplyPerYearInterestRateSlopeHigh;\n        uint64 supplyPerYearInterestRateBase;\n        uint64 borrowKink;\n        uint64 borrowPerYearInterestRateSlopeLow;\n        uint64 borrowPerYearInterestRateSlopeHigh;\n        uint64 borrowPerYearInterestRateBase;\n        uint64 storeFrontPriceFactor;\n        uint64 trackingIndexScale;\n        uint64 baseTrackingSupplySpeed;\n        uint64 baseTrackingBorrowSpeed;\n        uint104 baseMinForRewards;\n        uint104 baseBorrowMin;\n        uint104 targetReserves;\n\n        AssetConfig[] assetConfigs;\n    }\n\n    struct AssetConfig {\n        address asset;\n        address priceFeed;\n        uint8 decimals;\n        uint64 borrowCollateralFactor;\n        uint64 liquidateCollateralFactor;\n        uint64 liquidationFactor;\n        uint128 supplyCap;\n    }\n}\n"},{"file_path":"contracts/CometCore.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometConfiguration.sol\";\nimport \"./CometStorage.sol\";\nimport \"./CometMath.sol\";\n\nabstract contract CometCore is CometConfiguration, CometStorage, CometMath {\n    struct AssetInfo {\n        uint8 offset;\n        address asset;\n        address priceFeed;\n        uint64 scale;\n        uint64 borrowCollateralFactor;\n        uint64 liquidateCollateralFactor;\n        uint64 liquidationFactor;\n        uint128 supplyCap;\n    }\n\n    /** Internal constants **/\n\n    /// @dev The max number of assets this contract is hardcoded to support\n    ///  Do not change this variable without updating all the fields throughout the contract,\n    //    including the size of UserBasic.assetsIn and corresponding integer conversions.\n    uint8 internal constant MAX_ASSETS = 15;\n\n    /// @dev The max number of decimals base token can have\n    ///  Note this cannot just be increased arbitrarily.\n    uint8 internal constant MAX_BASE_DECIMALS = 18;\n\n    /// @dev The max value for a collateral factor (1)\n    uint64 internal constant MAX_COLLATERAL_FACTOR = FACTOR_SCALE;\n\n    /// @dev Offsets for specific actions in the pause flag bit array\n    uint8 internal constant PAUSE_SUPPLY_OFFSET = 0;\n    uint8 internal constant PAUSE_TRANSFER_OFFSET = 1;\n    uint8 internal constant PAUSE_WITHDRAW_OFFSET = 2;\n    uint8 internal constant PAUSE_ABSORB_OFFSET = 3;\n    uint8 internal constant PAUSE_BUY_OFFSET = 4;\n\n    /// @dev Offsets for specific actions in the extended pause flag bit array\n    /// @dev Offset of pause lenders withdraw\n    uint24 internal constant PAUSE_LENDERS_WITHDRAW_OFFSET = 0;\n    /// @dev Offset of pause borrowers withdraw\n    uint24 internal constant PAUSE_BORROWERS_WITHDRAW_OFFSET = 1;\n    /// @dev Offset of pause collateral supply\n    uint24 internal constant PAUSE_COLLATERAL_SUPPLY_OFFSET = 2;\n    /// @dev Offset of pause base supply\n    uint24 internal constant PAUSE_BASE_SUPPLY_OFFSET = 3;\n    /// @dev Offset of pause lenders transfer\n    uint24 internal constant PAUSE_LENDERS_TRANSFER_OFFSET = 4;\n    /// @dev Offset of pause borrowers transfer\n    uint24 internal constant PAUSE_BORROWERS_TRANSFER_OFFSET = 5;\n    /// @dev Offset of pause collateral transfer\n    uint24 internal constant PAUSE_COLLATERALS_TRANSFER_OFFSET = 6;\n    /// @dev Offset of pause collateral withdraw\n    uint24 internal constant PAUSE_COLLATERALS_WITHDRAW_OFFSET = 7;\n\n    /// @dev The decimals required for a price feed\n    uint8 internal constant PRICE_FEED_DECIMALS = 8;\n\n    /// @dev 365 days * 24 hours * 60 minutes * 60 seconds\n    uint64 internal constant SECONDS_PER_YEAR = 31_536_000;\n\n    /// @dev The scale for base tracking accrual\n    uint64 internal constant BASE_ACCRUAL_SCALE = 1e6;\n\n    /// @dev The scale for base index (depends on time/rate scales, not base token)\n    uint64 internal constant BASE_INDEX_SCALE = 1e15;\n\n    /// @dev The scale for prices (in USD)\n    uint64 internal constant PRICE_SCALE = uint64(10 ** PRICE_FEED_DECIMALS);\n\n    /// @dev The scale for factors\n    uint64 internal constant FACTOR_SCALE = 1e18;\n\n    /// @dev The storage slot for reentrancy guard flags\n    bytes32 internal constant REENTRANCY_GUARD_FLAG_SLOT = bytes32(keccak256(\"comet.reentrancy.guard\"));\n\n    /// @dev The reentrancy guard statuses\n    uint256 internal constant REENTRANCY_GUARD_NOT_ENTERED = 0;\n    uint256 internal constant REENTRANCY_GUARD_ENTERED = 1;\n\n    /**\n     * @notice Determine if the manager has permission to act on behalf of the owner\n     * @param owner The owner account\n     * @param manager The manager account\n     * @return Whether or not the manager has permission\n     */\n    function hasPermission(address owner, address manager) public view returns (bool) {\n        return owner == manager || isAllowed[owner][manager];\n    }\n\n    /**\n     * @dev The positive present supply balance if positive or the negative borrow balance if negative\n     */\n    function presentValue(int104 principalValue_) internal view returns (int256) {\n        if (principalValue_ >= 0) {\n            return signed256(presentValueSupply(baseSupplyIndex, uint104(principalValue_)));\n        } else {\n            return -signed256(presentValueBorrow(baseBorrowIndex, uint104(-principalValue_)));\n        }\n    }\n\n    /**\n     * @dev The principal amount projected forward by the supply index\n     */\n    function presentValueSupply(uint64 baseSupplyIndex_, uint104 principalValue_) internal pure returns (uint256) {\n        return uint256(principalValue_) * baseSupplyIndex_ / BASE_INDEX_SCALE;\n    }\n\n    /**\n     * @dev The principal amount projected forward by the borrow index\n     */\n    function presentValueBorrow(uint64 baseBorrowIndex_, uint104 principalValue_) internal pure returns (uint256) {\n        return uint256(principalValue_) * baseBorrowIndex_ / BASE_INDEX_SCALE;\n    }\n\n    /**\n     * @dev The positive principal if positive or the negative principal if negative\n     */\n    function principalValue(int256 presentValue_) internal view returns (int104) {\n        if (presentValue_ >= 0) {\n            return signed104(principalValueSupply(baseSupplyIndex, uint256(presentValue_)));\n        } else {\n            return -signed104(principalValueBorrow(baseBorrowIndex, uint256(-presentValue_)));\n        }\n    }\n\n    /**\n     * @dev The present value projected backward by the supply index (rounded down)\n     *  Note: This will overflow (revert) at 2^104/1e18=~20 trillion principal for assets with 18 decimals.\n     */\n    function principalValueSupply(uint64 baseSupplyIndex_, uint256 presentValue_) internal pure returns (uint104) {\n        return safe104((presentValue_ * BASE_INDEX_SCALE) / baseSupplyIndex_);\n    }\n\n    /**\n     * @dev The present value projected backward by the borrow index (rounded up)\n     *  Note: This will overflow (revert) at 2^104/1e18=~20 trillion principal for assets with 18 decimals.\n     */\n    function principalValueBorrow(uint64 baseBorrowIndex_, uint256 presentValue_) internal pure returns (uint104) {\n        return safe104((presentValue_ * BASE_INDEX_SCALE + baseBorrowIndex_ - 1) / baseBorrowIndex_);\n    }\n}\n"},{"file_path":"contracts/CometMainInterface.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometCore.sol\";\n\n/**\n * @title Compound's Comet Main Interface (without Ext)\n * @notice An efficient monolithic money market protocol\n * @author Compound\n */\nabstract contract CometMainInterface is CometCore {\n    error Absurd();\n    error AlreadyInitialized();\n    error BadAsset();\n    error BadDecimals();\n    error BadDiscount();\n    error BadMinimum();\n    error BadPrice();\n    error BorrowTooSmall();\n    error BorrowCFTooLarge();\n    error InsufficientReserves();\n    error LiquidateCFTooLarge();\n    error LiqPenaltyTooHigh();\n    error NoSelfTransfer();\n    error NotCollateralized();\n    error NotForSale();\n    error NotLiquidatable();\n    error Paused();\n    error ReentrantCallBlocked();\n    error SupplyCapExceeded();\n    error TimestampTooLarge();\n    error TooManyAssets();\n    error TooMuchSlippage();\n    error TransferInFailed();\n    error TransferOutFailed();\n    error Unauthorized();\n\n    /// @dev Error emitted when the utilization exceeds the supported utilization\n    error ExceedsSupportedUtilization();\n    /// @notice Error emitted when base supply is paused\n    error BaseSupplyPaused();\n    /// @notice Error emitted when collateral supply is paused\n    error CollateralSupplyPaused();\n    /// @notice Error emitted when a specific collateral asset supply is paused\n    /// @param assetIndex The index of the collateral asset\n    error CollateralAssetSupplyPaused(uint24 assetIndex);\n    /// @notice Error emitted when borrowers' transfers are paused\n    error BorrowersTransferPaused();\n    /// @notice Error emitted when lenders' transfers are paused\n    error LendersTransferPaused();\n    /// @notice Error emitted when collateral transfers are paused\n    error CollateralTransferPaused();\n    /// @notice Error emitted when a specific collateral asset transfer is paused\n    /// @param assetIndex The index of the collateral asset\n    error CollateralAssetTransferPaused(uint24 assetIndex);\n    /// @notice Error emitted when borrowers' withdrawals are paused\n    error BorrowersWithdrawPaused();\n    /// @notice Error emitted when lenders' withdrawals are paused\n    error LendersWithdrawPaused();\n    /// @notice Error emitted when collateral withdrawals are paused\n    error CollateralWithdrawPaused();\n    /// @notice Error emitted when a specific collateral asset withdrawal is paused\n    /// @param assetIndex The index of the collateral asset\n    error CollateralAssetWithdrawPaused(uint24 assetIndex);\n    /// @notice Error emitted when a user with debt tries to transfer and their position uses deactivated collateral\n    error DeactivatedCollateralTransferBlocked();\n    /// @notice Error emitted when trying to borrow or increase debt using deactivated collateral\n    error DeactivatedCollateralBorrowBlocked();\n    /// @notice Error emitted when deactivated token balance is > 0 on the balance of the account\n    error TokenIsDeactivated(address asset);\n\n    event Supply(address indexed from, address indexed dst, uint amount);\n    event Transfer(address indexed from, address indexed to, uint amount);\n    event Withdraw(address indexed src, address indexed to, uint amount);\n\n    event SupplyCollateral(address indexed from, address indexed dst, address indexed asset, uint amount);\n    event TransferCollateral(address indexed from, address indexed to, address indexed asset, uint amount);\n    event WithdrawCollateral(address indexed src, address indexed to, address indexed asset, uint amount);\n\n    /// @notice Event emitted when a borrow position is absorbed by the protocol\n    event AbsorbDebt(address indexed absorber, address indexed borrower, uint basePaidOut, uint usdValue);\n\n    /// @notice Event emitted when a user's collateral is absorbed by the protocol\n    event AbsorbCollateral(address indexed absorber, address indexed borrower, address indexed asset, uint collateralAbsorbed, uint usdValue);\n\n    /// @notice Event emitted when a collateral asset is purchased from the protocol\n    event BuyCollateral(address indexed buyer, address indexed asset, uint baseAmount, uint collateralAmount);\n\n    /// @notice Event emitted when an action is paused/unpaused\n    event PauseAction(bool supplyPaused, bool transferPaused, bool withdrawPaused, bool absorbPaused, bool buyPaused);\n\n    /// @notice Event emitted when reserves are withdrawn by the governor\n    event WithdrawReserves(address indexed to, uint amount);\n\n    function supply(address asset, uint amount) virtual external;\n    function supplyTo(address dst, address asset, uint amount) virtual external;\n    function supplyFrom(address from, address dst, address asset, uint amount) virtual external;\n\n    function transfer(address dst, uint amount) virtual external returns (bool);\n    function transferFrom(address src, address dst, uint amount) virtual external returns (bool);\n\n    function transferAsset(address dst, address asset, uint amount) virtual external;\n    function transferAssetFrom(address src, address dst, address asset, uint amount) virtual external;\n\n    function withdraw(address asset, uint amount) virtual external;\n    function withdrawTo(address to, address asset, uint amount) virtual external;\n    function withdrawFrom(address src, address to, address asset, uint amount) virtual external;\n\n    function approveThis(address manager, address asset, uint amount) virtual external;\n    function withdrawReserves(address to, uint amount) virtual external;\n\n    function absorb(address absorber, address[] calldata accounts) virtual external;\n    function buyCollateral(address asset, uint minAmount, uint baseAmount, address recipient) virtual external;\n    function quoteCollateral(address asset, uint baseAmount) virtual public view returns (uint);\n\n    function getAssetInfo(uint8 i) virtual public view returns (AssetInfo memory);\n    function getAssetInfoByAddress(address asset) virtual public view returns (AssetInfo memory);\n    function getCollateralReserves(address asset) virtual public view returns (uint);\n    function getReserves() virtual public view returns (int);\n    function getPrice(address priceFeed) virtual public view returns (uint);\n\n    function isBorrowCollateralized(address account) virtual public view returns (bool);\n    function isLiquidatable(address account) virtual public view returns (bool);\n\n    function totalSupply() virtual external view returns (uint256);\n    function totalBorrow() virtual external view returns (uint256);\n    function balanceOf(address owner) virtual public view returns (uint256);\n    function borrowBalanceOf(address account) virtual public view returns (uint256);\n\n    function pause(bool supplyPaused, bool transferPaused, bool withdrawPaused, bool absorbPaused, bool buyPaused) virtual external;\n    function isSupplyPaused() virtual public view returns (bool);\n    function isTransferPaused() virtual public view returns (bool);\n    function isWithdrawPaused() virtual public view returns (bool);\n    function isAbsorbPaused() virtual public view returns (bool);\n    function isBuyPaused() virtual public view returns (bool);\n\n    function accrueAccount(address account) virtual external;\n    function getSupplyRate(uint utilization) virtual public view returns (uint64);\n    function getBorrowRate(uint utilization) virtual public view returns (uint64);\n    function getUtilization() virtual public view returns (uint);\n\n    function governor() virtual external view returns (address);\n    function pauseGuardian() virtual external view returns (address);\n    function baseToken() virtual external view returns (address);\n    function baseTokenPriceFeed() virtual external view returns (address);\n    function extensionDelegate() virtual external view returns (address);\n\n    /// @dev uint64\n    function supplyKink() virtual external view returns (uint);\n    /// @dev uint64\n    function supplyPerSecondInterestRateSlopeLow() virtual external view returns (uint);\n    /// @dev uint64\n    function supplyPerSecondInterestRateSlopeHigh() virtual external view returns (uint);\n    /// @dev uint64\n    function supplyPerSecondInterestRateBase() virtual external view returns (uint);\n    /// @dev uint64\n    function borrowKink() virtual external view returns (uint);\n    /// @dev uint64\n    function borrowPerSecondInterestRateSlopeLow() virtual external view returns (uint);\n    /// @dev uint64\n    function borrowPerSecondInterestRateSlopeHigh() virtual external view returns (uint);\n    /// @dev uint64\n    function borrowPerSecondInterestRateBase() virtual external view returns (uint);\n    /// @dev uint64\n    function storeFrontPriceFactor() virtual external view returns (uint);\n\n    /// @dev uint64\n    function baseScale() virtual external view returns (uint);\n    /// @dev uint64\n    function trackingIndexScale() virtual external view returns (uint);\n\n    /// @dev uint64\n    function baseTrackingSupplySpeed() virtual external view returns (uint);\n    /// @dev uint64\n    function baseTrackingBorrowSpeed() virtual external view returns (uint);\n    /// @dev uint104\n    function baseMinForRewards() virtual external view returns (uint);\n    /// @dev uint104\n    function baseBorrowMin() virtual external view returns (uint);\n    /// @dev uint104\n    function targetReserves() virtual external view returns (uint);\n\n    function numAssets() virtual external view returns (uint8);\n    function decimals() virtual external view returns (uint8);\n\n    function initializeStorage() virtual external;\n}"},{"file_path":"contracts/CometMath.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title Compound's Comet Math Contract\n * @dev Pure math functions\n * @author Compound\n */\ncontract CometMath {\n    /** Custom errors **/\n\n    error InvalidUInt64();\n    error InvalidUInt104();\n    error InvalidUInt128();\n    error InvalidInt104();\n    error InvalidInt256();\n    error NegativeNumber();\n\n    function safe64(uint n) internal pure returns (uint64) {\n        if (n > type(uint64).max) revert InvalidUInt64();\n        return uint64(n);\n    }\n\n    function safe104(uint n) internal pure returns (uint104) {\n        if (n > type(uint104).max) revert InvalidUInt104();\n        return uint104(n);\n    }\n\n    function safe128(uint n) internal pure returns (uint128) {\n        if (n > type(uint128).max) revert InvalidUInt128();\n        return uint128(n);\n    }\n\n    function signed104(uint104 n) internal pure returns (int104) {\n        if (n > uint104(type(int104).max)) revert InvalidInt104();\n        return int104(n);\n    }\n\n    function signed256(uint256 n) internal pure returns (int256) {\n        if (n > uint256(type(int256).max)) revert InvalidInt256();\n        return int256(n);\n    }\n\n    function unsigned104(int104 n) internal pure returns (uint104) {\n        if (n < 0) revert NegativeNumber();\n        return uint104(n);\n    }\n\n    function unsigned256(int256 n) internal pure returns (uint256) {\n        if (n < 0) revert NegativeNumber();\n        return uint256(n);\n    }\n\n    function toUInt8(bool x) internal pure returns (uint8) {\n        return x ? 1 : 0;\n    }\n\n    function toBool(uint8 x) internal pure returns (bool) {\n        return x != 0;\n    }\n}\n"},{"file_path":"contracts/CometStorage.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title Compound's Comet Storage Interface\n * @dev Versions can enforce append-only storage slots via inheritance.\n * @author Compound\n */\ncontract CometStorage {\n    // 512 bits total = 2 slots\n    struct TotalsBasic {\n        // 1st slot\n        uint64 baseSupplyIndex;\n        uint64 baseBorrowIndex;\n        uint64 trackingSupplyIndex;\n        uint64 trackingBorrowIndex;\n        // 2nd slot\n        uint104 totalSupplyBase;\n        uint104 totalBorrowBase;\n        uint40 lastAccrualTime;\n        uint8 pauseFlags;\n    }\n\n    struct TotalsCollateral {\n        uint128 totalSupplyAsset;\n        uint128 _reserved;\n    }\n\n    struct UserBasic {\n        int104 principal;\n        uint64 baseTrackingIndex;\n        uint64 baseTrackingAccrued;\n        uint16 assetsIn;\n        uint8 _reserved;\n    }\n\n    struct UserCollateral {\n        uint128 balance;\n        uint128 _reserved;\n    }\n\n    struct LiquidatorPoints {\n        uint32 numAbsorbs;\n        uint64 numAbsorbed;\n        uint128 approxSpend;\n        uint32 _reserved;\n    }\n\n    /// @dev Aggregate variables tracked for the entire market\n    uint64 internal baseSupplyIndex;\n    uint64 internal baseBorrowIndex;\n    uint64 internal trackingSupplyIndex;\n    uint64 internal trackingBorrowIndex;\n    uint104 internal totalSupplyBase;\n    uint104 internal totalBorrowBase;\n    uint40 internal lastAccrualTime;\n    uint8 internal pauseFlags;\n\n    /// @notice Aggregate variables tracked for each collateral asset\n    mapping(address => TotalsCollateral) public totalsCollateral;\n\n    /// @notice Mapping of users to accounts which may be permitted to manage the user account\n    mapping(address => mapping(address => bool)) public isAllowed;\n\n    /// @notice The next expected nonce for an address, for validating authorizations via signature\n    mapping(address => uint) public userNonce;\n\n    /// @notice Mapping of users to base principal and other basic data\n    mapping(address => UserBasic) public userBasic;\n\n    /// @notice Mapping of users to collateral data per collateral asset\n    mapping(address => mapping(address => UserCollateral)) public userCollateral;\n\n    /// @notice Mapping of magic liquidator points\n    mapping(address => LiquidatorPoints) public liquidatorPoints;\n\n    /**\n     * @notice The extended pause flags represented as a bitmap\n     * @dev Each bit represents a pause flag for a different action\n     */\n    uint24 public extendedPauseFlags;\n\n    /**\n     * @notice The collaterals withdraw pause flags represented as a bitmap\n     * @dev Each bit represents a pause flag for an asset index\n     */\n    uint24 public collateralsWithdrawPauseFlags;\n\n    /**\n     * @notice The collaterals supply pause flags represented as a bitmap\n     * @dev Each bit represents a pause flag for an asset index\n     */\n    uint24 public collateralsSupplyPauseFlags;\n\n    /**\n     * @notice The collaterals transfer pause flags represented as a bitmap\n     * @dev Each bit represents a pause flag for an asset index\n     */\n    uint24 public collateralsTransferPauseFlags;\n\n    /**\n     * @notice The deactivated collaterals flags represented as a bitmap\n     * @dev Each bit represents whether a collateral asset is deactivated\n     */\n    uint24 public deactivatedCollaterals;\n}\n"},{"file_path":"contracts/IAssetList.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometCore.sol\";\n\n/**\n * @title Compound's Asset List\n * @author Compound\n */\ninterface IAssetList {\n    function getAssetInfo(uint8 i) external view returns (CometCore.AssetInfo memory);\n    function numAssets() external view returns (uint8);\n}"},{"file_path":"contracts/IERC20NonStandard.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title IERC20NonStandard\n * @dev Version of ERC20 with no return values for `approve`, `transfer`, and `transferFrom`\n *  See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ninterface IERC20NonStandard {\n    function name() external view returns (string memory);\n    function symbol() external view returns (string memory);\n    function decimals() external view returns (uint8);\n\n    /**\n     * @notice Approve `spender` to transfer up to `amount` from `src`\n     * @dev This will overwrite the approval amount for `spender`\n     *  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n     * @param spender The address of the account which may transfer tokens\n     * @param amount The number of tokens that are approved (-1 means infinite)\n     */\n    function approve(address spender, uint256 amount) external;\n\n    /**\n     * @notice Transfer `value` tokens from `msg.sender` to `to`\n     * @param to The address of the destination account\n     * @param value The number of tokens to transfer\n     */\n    function transfer(address to, uint256 value) external;\n\n    /**\n     * @notice Transfer `value` tokens from `from` to `to`\n     * @param from The address of the source account\n     * @param to The address of the destination account\n     * @param value The number of tokens to transfer\n     */\n    function transferFrom(address from, address to, uint256 value) external;\n\n    /**\n     * @notice Gets the balance of the specified address\n     * @param account The address from which the balance will be retrieved\n     */\n    function balanceOf(address account) external view returns (uint256);\n}\n"},{"file_path":"contracts/IPriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @dev Interface for price feeds used by Comet\n * Note This is Chainlink's AggregatorV3Interface, but without the `getRoundData` function.\n */\ninterface IPriceFeed {\n  function decimals() external view returns (uint8);\n\n  function description() external view returns (string memory);\n\n  function version() external view returns (uint256);\n\n  function latestRoundData()\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n}"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"components":[{"internalType":"address","name":"governor","type":"address"},{"internalType":"address","name":"pauseGuardian","type":"address"},{"internalType":"address","name":"baseToken","type":"address"},{"internalType":"address","name":"baseTokenPriceFeed","type":"address"},{"internalType":"address","name":"extensionDelegate","type":"address"},{"internalType":"uint64","name":"supplyKink","type":"uint64"},{"internalType":"uint64","name":"supplyPerYearInterestRateSlopeLow","type":"uint64"},{"internalType":"uint64","name":"supplyPerYearInterestRateSlopeHigh","type":"uint64"},{"internalType":"uint64","name":"supplyPerYearInterestRateBase","type":"uint64"},{"internalType":"uint64","name":"borrowKink","type":"uint64"},{"internalType":"uint64","name":"borrowPerYearInterestRateSlopeLow","type":"uint64"},{"internalType":"uint64","name":"borrowPerYearInterestRateSlopeHigh","type":"uint64"},{"internalType":"uint64","name":"borrowPerYearInterestRateBase","type":"uint64"},{"internalType":"uint64","name":"storeFrontPriceFactor","type":"uint64"},{"internalType":"uint64","name":"trackingIndexScale","type":"uint64"},{"internalType":"uint64","name":"baseTrackingSupplySpeed","type":"uint64"},{"internalType":"uint64","name":"baseTrackingBorrowSpeed","type":"uint64"},{"internalType":"uint104","name":"baseMinForRewards","type":"uint104"},{"internalType":"uint104","name":"baseBorrowMin","type":"uint104"},{"internalType":"uint104","name":"targetReserves","type":"uint104"},{"components":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint64","name":"borrowCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidateCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidationFactor","type":"uint64"},{"internalType":"uint128","name":"supplyCap","type":"uint128"}],"internalType":"struct CometConfiguration.AssetConfig[]","name":"assetConfigs","type":"tuple[]"}],"internalType":"struct CometConfiguration.Configuration","name":"config","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Absurd","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BadAsset","type":"error"},{"inputs":[],"name":"BadDecimals","type":"error"},{"inputs":[],"name":"BadDiscount","type":"error"},{"inputs":[],"name":"BadMinimum","type":"error"},{"inputs":[],"name":"BadPrice","type":"error"},{"inputs":[],"name":"BaseSupplyPaused","type":"error"},{"inputs":[],"name":"BorrowCFTooLarge","type":"error"},{"inputs":[],"name":"BorrowTooSmall","type":"error"},{"inputs":[],"name":"BorrowersTransferPaused","type":"error"},{"inputs":[],"name":"BorrowersWithdrawPaused","type":"error"},{"inputs":[{"internalType":"uint24","name":"assetIndex","type":"uint24"}],"name":"CollateralAssetSupplyPaused","type":"error"},{"inputs":[{"internalType":"uint24","name":"assetIndex","type":"uint24"}],"name":"CollateralAssetTransferPaused","type":"error"},{"inputs":[{"internalType":"uint24","name":"assetIndex","type":"uint24"}],"name":"CollateralAssetWithdrawPaused","type":"error"},{"inputs":[],"name":"CollateralSupplyPaused","type":"error"},{"inputs":[],"name":"CollateralTransferPaused","type":"error"},{"inputs":[],"name":"CollateralWithdrawPaused","type":"error"},{"inputs":[],"name":"DeactivatedCollateralBorrowBlocked","type":"error"},{"inputs":[],"name":"DeactivatedCollateralTransferBlocked","type":"error"},{"inputs":[],"name":"ExceedsSupportedUtilization","type":"error"},{"inputs":[],"name":"InsufficientReserves","type":"error"},{"inputs":[],"name":"InvalidInt104","type":"error"},{"inputs":[],"name":"InvalidInt256","type":"error"},{"inputs":[],"name":"InvalidUInt104","type":"error"},{"inputs":[],"name":"InvalidUInt128","type":"error"},{"inputs":[],"name":"InvalidUInt64","type":"error"},{"inputs":[],"name":"LendersTransferPaused","type":"error"},{"inputs":[],"name":"LendersWithdrawPaused","type":"error"},{"inputs":[],"name":"LiqPenaltyTooHigh","type":"error"},{"inputs":[],"name":"LiquidateCFTooLarge","type":"error"},{"inputs":[],"name":"NegativeNumber","type":"error"},{"inputs":[],"name":"NoSelfTransfer","type":"error"},{"inputs":[],"name":"NotCollateralized","type":"error"},{"inputs":[],"name":"NotForSale","type":"error"},{"inputs":[],"name":"NotLiquidatable","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"ReentrantCallBlocked","type":"error"},{"inputs":[],"name":"SupplyCapExceeded","type":"error"},{"inputs":[],"name":"TimestampTooLarge","type":"error"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"TokenIsDeactivated","type":"error"},{"inputs":[],"name":"TooManyAssets","type":"error"},{"inputs":[],"name":"TooMuchSlippage","type":"error"},{"inputs":[],"name":"TransferInFailed","type":"error"},{"inputs":[],"name":"TransferOutFailed","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"absorber","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"collateralAbsorbed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdValue","type":"uint256"}],"name":"AbsorbCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"absorber","type":"address"},{"indexed":true,"internalType":"address","name":"borrower","type":"address"},{"indexed":false,"internalType":"uint256","name":"basePaidOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdValue","type":"uint256"}],"name":"AbsorbDebt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"baseAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"BuyCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"supplyPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"transferPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"withdrawPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"absorbPaused","type":"bool"},{"indexed":false,"internalType":"bool","name":"buyPaused","type":"bool"}],"name":"PauseAction","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Supply","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"SupplyCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawReserves","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"MAX_SUPPORTED_UTILIZATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"absorber","type":"address"},{"internalType":"address[]","name":"accounts","type":"address[]"}],"name":"absorb","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"accrueAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveThis","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"assetList","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseBorrowMin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseMinForRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenPriceFeed","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTrackingBorrowSpeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTrackingSupplySpeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"borrowBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowKink","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowPerSecondInterestRateBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowPerSecondInterestRateSlopeHigh","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"borrowPerSecondInterestRateSlopeLow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"minAmount","type":"uint256"},{"internalType":"uint256","name":"baseAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"buyCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collateralsSupplyPauseFlags","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralsTransferPauseFlags","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collateralsWithdrawPauseFlags","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deactivatedCollaterals","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extendedPauseFlags","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extensionDelegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"i","type":"uint8"}],"name":"getAssetInfo","outputs":[{"components":[{"internalType":"uint8","name":"offset","type":"uint8"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint64","name":"scale","type":"uint64"},{"internalType":"uint64","name":"borrowCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidateCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidationFactor","type":"uint64"},{"internalType":"uint128","name":"supplyCap","type":"uint128"}],"internalType":"struct CometCore.AssetInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getAssetInfoByAddress","outputs":[{"components":[{"internalType":"uint8","name":"offset","type":"uint8"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"priceFeed","type":"address"},{"internalType":"uint64","name":"scale","type":"uint64"},{"internalType":"uint64","name":"borrowCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidateCollateralFactor","type":"uint64"},{"internalType":"uint64","name":"liquidationFactor","type":"uint64"},{"internalType":"uint128","name":"supplyCap","type":"uint128"}],"internalType":"struct CometCore.AssetInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"utilization","type":"uint256"}],"name":"getBorrowRate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"getCollateralReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"priceFeed","type":"address"}],"name":"getPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"utilization","type":"uint256"}],"name":"getSupplyRate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUtilization","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"manager","type":"address"}],"name":"hasPermission","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initializeStorage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isAbsorbPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBaseSupplyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isBorrowCollateralized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBorrowersTransferPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBorrowersWithdrawPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBuyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"assetIndex","type":"uint24"}],"name":"isCollateralAssetSupplyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"assetIndex","type":"uint24"}],"name":"isCollateralAssetTransferPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"assetIndex","type":"uint24"}],"name":"isCollateralAssetWithdrawPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"assetIndex","type":"uint24"}],"name":"isCollateralDeactivated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCollateralSupplyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCollateralTransferPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCollateralWithdrawPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLendersTransferPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLendersWithdrawPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isLiquidatable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSupplyPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTransferPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWithdrawPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"liquidatorPoints","outputs":[{"internalType":"uint32","name":"numAbsorbs","type":"uint32"},{"internalType":"uint64","name":"numAbsorbed","type":"uint64"},{"internalType":"uint128","name":"approxSpend","type":"uint128"},{"internalType":"uint32","name":"_reserved","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numAssets","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"supplyPaused","type":"bool"},{"internalType":"bool","name":"transferPaused","type":"bool"},{"internalType":"bool","name":"withdrawPaused","type":"bool"},{"internalType":"bool","name":"absorbPaused","type":"bool"},{"internalType":"bool","name":"buyPaused","type":"bool"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseGuardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"baseAmount","type":"uint256"}],"name":"quoteCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"storeFrontPriceFactor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"supplyFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supplyKink","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyPerSecondInterestRateBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyPerSecondInterestRateSlopeHigh","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"supplyPerSecondInterestRateSlopeLow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"supplyTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"targetReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBorrow","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"totalsCollateral","outputs":[{"internalType":"uint128","name":"totalSupplyAsset","type":"uint128"},{"internalType":"uint128","name":"_reserved","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trackingIndexScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferAssetFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBasic","outputs":[{"internalType":"int104","name":"principal","type":"int104"},{"internalType":"uint64","name":"baseTrackingIndex","type":"uint64"},{"internalType":"uint64","name":"baseTrackingAccrued","type":"uint64"},{"internalType":"uint16","name":"assetsIn","type":"uint16"},{"internalType":"uint8","name":"_reserved","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"userCollateral","outputs":[{"internalType":"uint128","name":"balance","type":"uint128"},{"internalType":"uint128","name":"_reserved","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawReserves","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTo","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}