{"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":"0x60806040526004361015610018575b61001661511f565b005b60003560e01c8063042e02cf146106d05780630546e6ec146106c75780630902f1ac146106be5780630bc47ad1146106b55780630c340a24146106ac57806318160ddd146106a3578063189bb2f11461069a5780631c9f7fb9146106915780631f5954bd14610688578063214435621461067f57806323b872dd1461067657806324a3d6221461066d578063264413181461066457806329c5a1a01461065b5780632a48cf12146106525780632b92a07d146106495780632d05670b146106405780632e04b8e714610637578063300e6beb1461062e578063313ce5671461062557806332176c491461061c578063374c49b41461061357806338aa813f1461060a5780633b3bec2e1461060157806341976e09146105f85780634232cd63146105ef578063439e2e45146105e657806344c1e5eb146105dd57806344c35d07146105d457806344ff241d146105cb5780634a95a76a146105c257806350a1efea146105b957806359e017bd146105b05780635a94b8d1146105a757806367800b5f1461059e5780636f678cce1461059557806370a082311461058c5780637914acc7146105835780637ac88ed11461057a5780637eb7113114610571578063804de71f146105685780638285ef401461055f5780638a5704df146105565780638d5d814c1461054d57806390323177146105445780639241a5611461053b5780639364e18a1461053257806394920cca146105295780639545e4de146105205780639ae3890c146105175780639ea99a5a1461050e5780639fa83b5a146105055780639ff567f8146104fc578063a1654379146104f3578063a1a1ef43146104ea578063a46fe83b146104e1578063a5b4ff79146104d8578063a9059cbb146104cf578063aba7f15e146104c6578063ad14777c146104bd578063b2a7a721146104b4578063bfe69c8d146104ab578063c04a5b06146104a2578063c1ee2c1814610499578063c3b35a7e14610490578063c3cecfd214610487578063c55dae631461047e578063c5fa15cf14610475578063c82643b41461046c578063c8c7fe6b14610463578063cde680411461045a578063cdfadab614610451578063ce26a7b014610448578063d8e5f6111461043f578063d955759d14610436578063dc4abafd1461042d578063e1066c9014610424578063e30ca4041461041b578063e372f03a14610412578063e478795d14610409578063e4e6e77914610400578063e719dc74146103f7578063e7dad6bd146103ee578063f2b9fdb8146103e5578063f3fef3a3146103dc5763fddc530f0361000e576103d7611e89565b61000e565b506103d7611e54565b506103d7611e20565b506103d7611dda565b506103d7611db7565b506103d7611c2e565b506103d7611b43565b506103d7611afd565b506103d7611ad9565b506103d7611ab2565b506103d7611a3f565b506103d7611a20565b506103d76119f9565b506103d76119d5565b506103d76119ba565b506103d761199e565b506103d7611975565b506103d7611946565b506103d76118d8565b506103d7611892565b506103d761182d565b506103d7611809565b506103d76117e3565b506103d76117bc565b506103d7611796565b506103d761176f565b506103d76116ca565b506103d761168e565b506103d7611638565b506103d76115fc565b506103d76115bd565b506103d7611596565b506103d7611555565b506103d761152d565b506103d76114fc565b506103d76114c0565b506103d76114a5565b506103d761148a565b506103d761144e565b506103d7611412565b506103d76113d6565b506103d76113b1565b506103d761138a565b506103d7611367565b506103d7611306565b506103d76112ca565b506103d76112ae565b506103d7611282565b506103d7611246565b506103d761121e565b506103d76111fa565b506103d76111d3565b506103d7611197565b506103d7611141565b506103d761111d565b506103d76110f6565b506103d76110b0565b506103d7610f31565b506103d7610ee8565b506103d7610ec4565b506103d7610ea1565b506103d7610e79565b506103d7610e44565b506103d7610d78565b506103d7610d50565b506103d7610d14565b506103d7610cd5565b506103d7610c99565b506103d7610c5b565b506103d7610c1f565b506103d7610bca565b506103d7610b1c565b506103d7610ae5565b506103d7610a90565b506103d7610a13565b506103d76109b0565b506103d761095f565b506103d7610923565b506103d761089d565b506103d7610861565b506103d76107f5565b506103d76107af565b506103d7610776565b506103d7610752565b506103d761072e565b506103d76106ef565b6001600160a01b038116036106ea57565b600080fd5b50346106ea5760203660031901126106ea576020610717600435610712816106d9565b613063565b50506040519015158152f35b60009103126106ea57565b50346106ea5760003660031901126106ea5760206080600854161515604051908152f35b50346106ea5760003660031901126106ea57602061076e612b7a565b604051908152f35b50346106ea5760003660031901126106ea5760206001805460f81c161515604051908152f35b6001600160a01b03909116815260200190565b50346106ea5760003660031901126106ea576040517f0000000000000000000000003fb4d38ea7ec20d91917c09591490eeda38cf88a6001600160a01b03168152602090f35b50346106ea5760003660031901126106ea57602066038d7ea4c6800061085861081c612170565b61083f6001549161083964ffffffffff91828560d01c169061226c565b16612520565b506001600160401b0316906001600160681b031661229a565b04604051908152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576000806003193601126109205760015464ffffffffff8160d01c1661090f5764ffffffffff60d01b6108d3612170565b64ffffffffff60d01b1990921660d09290921b161760015580546001600160801b0319166e038d7ea4c6800000038d7ea4c68000178155604051f35b60405162dc149f60e41b8152600490fd5b80fd5b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000853a0d2313c00008152f35b50346106ea5760003660031901126106ea5760206001600854161515604051908152f35b908160609103126106ea578035610999816106d9565b91604060208301356109aa816106d9565b92013590565b50346106ea576109f66109c4366004610983565b91906109ce613752565b7f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58319133614053565b600060008051602061517f83398151915255602060405160018152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000078e6317dd6d43ddbda00dce32c2cbafc99361a9d6001600160a01b03168152602090f35b91908260809103126106ea578135610a70816106d9565b916020810135610a7f816106d9565b91606060408301356109aa816106d9565b50346106ea57610ab6610aa4366004610a59565b92610ab0929192613752565b336145af565b600060008051602061517f83398151915255005b908160209103126106ea573562ffffff811681036106ea5790565b50346106ea576020610b12610afb366004610aca565b60085460601c600162ffffff8093161b1616151590565b6040519015158152f35b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000000001a942ee5c58152f35b91908260409103126106ea5760208235610b71816106d9565b920135610b7d816106d9565b90565b9060018060a01b0316600052602052604060002090565b6001600160801b031690565b546001600160801b031690565b6001600160801b0391821681529116602082015260400190565b50346106ea57610c1b610bff610be1366004610b58565b6001600160a01b039091166000908152600660205260409020610b80565b54604051918291608081901c906001600160801b031683610bb0565b0390f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000348078298152f35b50346106ea5760203660031901126106ea57600435610c79816106d9565b60018060a01b031660005260046020526020604060002054604051908152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000018152f35b50346106ea5760003660031901126106ea57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000006168152f35b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000000048c273950008152f35b50346106ea5760203660031901126106ea57602061076e600435610d73816106d9565b6150d7565b50346106ea5760203660031901126106ea576020610b12600435610d9b816106d9565b612cdf565b6001600160401b031690565b610e429092919260e08061010083019560ff815116845260018060a01b03806020830151166020860152604082015116604085015260018060401b036060820151166060850152610e0c6080820151608086019060018060401b03169052565b60a0818101516001600160401b03169085015260c0818101516001600160401b03169085015201516001600160801b0316910152565b565b50346106ea5760203660031901126106ea57610c1b610e6d600435610e68816106d9565b6120ec565b60405191829182610dac565b50346106ea5760203660031901126106ea57602061076e600435610e9c816106d9565b6129d7565b50346106ea57610ab6610eb5366004610983565b91610ebe613752565b3361366a565b50346106ea57610ab6610ed8366004610983565b91610ee1613752565b3333614053565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000f42408152f35b359081151582036106ea57565b50346106ea5760a03660031901126106ea57610f4d6004610f24565b610f576024610f24565b610f616044610f24565b91610f6c6064610f24565b92610f776084610f24565b60018060a01b03807f0000000000000000000000003fb4d38ea7ec20d91917c09591490eeda38cf88a163314159081611083575b50611072577f3be39979091ae7ca962aa1c44e645f2df3c221b79f324afa5f44aedc8d2f690d9461106d92611038610ff56000610fe788613278565b9060ff8080931691161b1690565b6110036001610fe78a613278565b176110126002610fe785613278565b176110216003610fe786613278565b176110306004610fe787613278565b176001613255565b6040519586958693909594919260809360a0860197151586521515602086015215156040850152151560608401521515910152565b0390a1005b6040516282b42960e81b8152600490fd5b90507f00000000000000000000000078e6317dd6d43ddbda00dce32c2cbafc99361a9d1633141538610fab565b50346106ea5760003660031901126106ea576040517f0000000000000000000000000d4bd55a755134950027ce1f43190a354e648e206001600160a01b03168152602090f35b50346106ea5760003660031901126106ea57602062ffffff60085460601c16604051908152f35b50346106ea5760003660031901126106ea576020604051671bc16d674ec800008152f35b50346106ea5760203660031901126106ea5760043561115f816106d9565b6001600160a01b031660009081526002602052604090819020549051908190610c1b90608081901c906001600160801b031683610bb0565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000440ab57f8152f35b50346106ea5760003660031901126106ea576020600460015460f81c161515604051908152f35b50346106ea5760003660031901126106ea5760206040600854161515604051908152f35b50346106ea5760203660031901126106ea57602061076e600435611241816106d9565b615079565b50346106ea5760003660031901126106ea5760206040517f000000000000000000000000000000000000000000000000000000001c59cb9f8152f35b50346106ea5760403660031901126106ea57602061076e6004356112a5816106d9565b60243590614f40565b50346106ea5760003660031901126106ea57602061076e612949565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000017989a464c8152f35b50346106ea5760003660031901126106ea57602066038d7ea4c6800061085861132d612170565b61134a6001549161083964ffffffffff91828560d01c169061226c565b6001600160401b03169160681c6001600160681b0316905061229a565b50346106ea5760003660031901126106ea57602060088054161515604051908152f35b50346106ea5760003660031901126106ea576020600860015460f81c161515604051908152f35b50346106ea57610ab66113c5366004610a59565b926113d1929192613752565b61366a565b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000c7d713b49da00008152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000002540be4008152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576020610b126114a0366004610aca565b6132b4565b50346106ea576020610b126114bb366004610aca565b61329d565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760203660031901126106ea57602061151b600435612842565b6040516001600160401b039091168152f35b50346106ea5760203660031901126106ea57602061076e600435611550816106d9565b612a82565b50346106ea57602060ff61158a61156d366004610b58565b6001600160a01b0390911660009081526003855260409020610b80565b54166040519015158152f35b50346106ea5760003660031901126106ea576020600260015460f81c161515604051908152f35b50346106ea5760003660031901126106ea57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000009168152f35b50346106ea5760003660031901126106ea5760206040517f0000000000000000000000000000000000000000000000000c7d713b49da00008152f35b50346106ea5760403660031901126106ea576109f6600435611659816106d9565b611661613752565b602435907f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831903333614053565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000038d7ea4c680008152f35b50346106ea576116db366004610983565b91906001600160a01b03907f0000000000000000000000003fb4d38ea7ec20d91917c09591490eeda38cf88a82163303611072571691823b156106ea5761173c926000928360405180968195829463095ea7b360e01b8452600484016147fe565b03925af18015611762575b61174d57005b8061175c600061001693611f01565b80610723565b61176a611fb0565b611747565b50346106ea5760003660031901126106ea57602062ffffff60085460181c16604051908152f35b50346106ea5760203660031901126106ea576100166004356117b7816106d9565b6121e4565b50346106ea5760003660031901126106ea57602062ffffff60085460301c16604051908152f35b50346106ea57610ab66117f7366004610a59565b92611803929192613752565b33614053565b50346106ea57610ab661181d366004610983565b91611826613752565b33336145af565b50346106ea5760403660031901126106ea5760043561184b816106d9565b602435906001600160401b03908183116106ea57366023840112156106ea5782600401359182116106ea573660248360051b850101116106ea576024610016930190614a37565b50346106ea5760003660031901126106ea576040517f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58316001600160a01b03168152602090f35b50346106ea5760203660031901126106ea576004356118f6816106d9565b60018060a01b0316600052600760205260806040600020546040519063ffffffff8116825260018060401b038160201c166020830152600180841b038160601c16604083015260e01c6060820152f35b50346106ea5760003660031901126106ea5760206010600854161515604051908152f35b60ff8116036106ea57565b50346106ea5760203660031901126106ea57610c1b610e6d6004356119998161196a565b611fbd565b50346106ea576020610b126119b4366004610b58565b90611ead565b50346106ea576020610b126119d0366004610aca565b613286565b50346106ea5760003660031901126106ea5760206002600854161515604051908152f35b50346106ea5760003660031901126106ea576020601060015460f81c161515604051908152f35b50346106ea5760203660031901126106ea57602061151b6004356125d8565b50346106ea5760203660031901126106ea57600435611a5d816106d9565b60018060a01b0316600052600560205260a06040600020546040519080600c0b825260018060401b03808260681c1660208401528160a81c16604083015261ffff8160e81c16606083015260f81c6080820152f35b50346106ea5760003660031901126106ea57602062ffffff60085460481c16604051908152f35b50346106ea5760003660031901126106ea57602062ffffff60085416604051908152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000090dcbcdc49195776b8807f01d9f127f9317674bb6001600160a01b03168152602090f35b50346106ea5760403660031901126106ea57600435611b61816106d9565b602435906001600160a01b037f0000000000000000000000003fb4d38ea7ec20d91917c09591490eeda38cf88a8116330361107257611b9e612b7a565b60008112908115611c1c575b50611c0a5781611bfc847fec4431f2ba1a9382f6b0c4352b888cba6f7db91667d9f776abe5ad8ddc5401b6947f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831614819565b6040519384521691602090a2005b60405163128bd24d60e31b8152600490fd5b611c269150614f35565b831138611baa565b50346106ea5760803660031901126106ea57600435611c4c816106d9565b60643590611c59826106d9565b611c61613752565b601060015460f81c16611da557611c76612b7a565b60008112159081611d7a575b50611d6857611cb4604435337f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831613b50565b90611cbf8282614f40565b926024358410611d5657611cd282612a82565b8411611c0a577ff891b2a411b0e66a5f0a6ff1368670fefa287a13f541eb633a386a1a9cc7046b91611d19611d3c92611d12611d0d8861372c565b610b97565b9083614819565b6040805194855260208501959095526001600160a01b0316933393918291820190565b0390a3610016600060008051602061517f83398151915255565b60405163fa6ad35560e01b8152600490fd5b604051631d99ddbf60e01b8152600490fd5b90507f0000000000000000000000000000000000000000000000000000048c27395000111538611c82565b6040516313d0ff5960e31b8152600490fd5b50346106ea5760003660031901126106ea57602080600854161515604051908152f35b50346106ea5760003660031901126106ea576040517f000000000000000000000000880d36763bb470cd395b7d6c76b50446fa70ace56001600160a01b03168152602090f35b50346106ea5760403660031901126106ea57610ab6600435611e41816106d9565b611e49613752565b60243590333361366a565b50346106ea5760403660031901126106ea57610ab6600435611e75816106d9565b611e7d613752565b602435903333336145af565b50346106ea5760003660031901126106ea5760206004600854161515604051908152f35b6001600160a01b03808316911690811491908215611eca57505090565b60ff925090611ee59160005260036020526040600020610b80565b541690565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017611f2457604052565b611f2c611eea565b604052565b60405190611f4161010083611f01565b8160e06000918281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b5190610e428261196a565b5190610e42826106d9565b51906001600160401b03821682036106ea57565b51906001600160801b03821682036106ea57565b506040513d6000823e3d90fd5b611fc5611f31565b5060405163c8c7fe6b60e01b815260ff91909116600482015261010080826024817f00000000000000000000000090dcbcdc49195776b8807f01d9f127f9317674bb6001600160a01b03165afa9182156120df575b60009261202657505090565b90918282813d83116120d8575b61203d8183611f01565b81010312610920575060e06120d0916120596040519485611f01565b61206281611f72565b845261207060208201611f7d565b602085015261208160408201611f7d565b604085015261209260608201611f88565b60608501526120a360808201611f88565b60808501526120b460a08201611f88565b60a08501526120c560c08201611f88565b60c085015201611f9c565b60e082015290565b503d612033565b6120e7611fb0565b61201a565b906120f5611f31565b5060009060ff92837f000000000000000000000000000000000000000000000000000000000000000916925b838582161061213c57604051633640530560e01b8152600490fd5b61214581611fbd565b60208101516001600160a01b0384811691161461216757506001018416612121565b93505050915090565b600160281b4210156121875764ffffffffff421690565b604051633d32ffdb60e01b8152600490fd5b906040516121a860a082611f01565b608081935480600c0b835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c910152565b610e42906121f06122f1565b60018060a01b038116600052600560205260406000206040519061221560a083611f01565b549182600c0b9283835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c6080830152613504565b50634e487b7160e01b600052601160045260246000fd5b64ffffffffff9182169116818110612282570390565b61228a612255565b0390565b6001600160681b031690565b80600019048211811515166122ad570290565b6122b5612255565b0290565b6001600160401b03918216919081169082900381116122d6570190565b6122de612255565b0190565b60681c6001600160681b031690565b6122f9612170565b61232361231961231360015464ffffffffff9060d01c1690565b8361226c565b64ffffffffff1690565b908161232d575050565b8161238461233d610e4294612520565b60008054600160401b600160801b03191660409290921b600160401b600160801b0316919091178155919082546001600160401b0319166001600160401b03909116178255565b61238f60015461228e565b7f00000000000000000000000000000000000000000000000000000002540be40092906001600160681b031683811015612484575b506123d86123d36001546122e2565b61228e565b9283101561240c575b50506001805464ffffffffff60d01b191660d09390931b64ffffffffff60d01b169290921790915550565b61244d61244861247c9461244361245c947f000000000000000000000000000000000000000000000000000000000000000061229a565b6132de565b6124fa565b825460c01c6122b9565b6122b9565b81546001600160c01b031660c09190911b6001600160c01b031916179055565b3880806123e1565b6124ce6124bb6124486124f493612443867f000000000000000000000000000000000000000000000000000000000000000061229a565b845460801c6001600160401b03166122b9565b8354600160801b600160c01b03191660809190911b600160801b600160c01b0316178355565b386123c4565b6001600160401b039081811161250e571690565b6040516372a1cb5160e11b8152600490fd5b6000546001600160401b03604082901c81169392918116919081612545575b50509190565b8161259861259261257297946125a46125aa9761259e8761257961259e9961256b612949565b9e8f6125d8565b169d612842565b169b612598612592670de0b6b3a7640000998a9361229a565b8461229a565b046124fa565b906122b9565b9861229a565b91388061253f565b908160209103126106ea575190565b811981116122d6570190565b818110612282570390565b6125e360015461228e565b6001600160681b038116156127e9578115806127c0575b6126ff575b507f0000000000000000000000000000000000000000000000000c7d713b49da00008082116126895750612448670de0b6b3a7640000612662610b7d937f00000000000000000000000000000000000000000000000000000000440ab57f61229a565b047f00000000000000000000000000000000000000000000000000000000000000006125c1565b610b7d916126f96126d3836126cd670de0b6b3a7640000612662612448977f00000000000000000000000000000000000000000000000000000000440ab57f61229a565b936125cd565b7f00000000000000000000000000000000000000000000000000000017989a464c6132cb565b906125c1565b6127139061270e600054610da0565b61281d565b6040516370a0823160e01b81529060208280612732306004830161079c565b03817f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58316001600160a01b03165afa9182156127b3575b600092612783575b50101561277d57386125ff565b50600090565b6127a591925060203d81116127ac575b61279d8183611f01565b8101906125b2565b9038612770565b503d612793565b6127bb611fb0565b612768565b507f000000000000000000000000000000000000000000000000000000000000000015156125fa565b5050600090565b50634e487b7160e01b600052601260045260246000fd5b8115612811570490565b6128196127f0565b0490565b66038d7ea4c6800091612819916001600160401b0316906001600160681b031661229a565b60015460681c6001600160681b03161561277d577f0000000000000000000000000000000000000000000000000c7d713b49da00008082116128df5750612448670de0b6b3a76400006128b8610b7d937f000000000000000000000000000000000000000000000000000000003480782961229a565b047f000000000000000000000000000000000000000000000000000000001c59cb9f6125c1565b610b7d916126f9612923836126cd670de0b6b3a76400006128b8612448977f000000000000000000000000000000000000000000000000000000003480782961229a565b7f0000000000000000000000000000000000000000000000000000001a942ee5c56132cb565b60005460015466038d7ea4c680009061298b906001600160681b036001600160401b038461297b82881684861661229a565b049560401c169160681c1661229a565b0481612998575050600090565b670de0b6b3a76400009080600019048211811515166129b657020490565b6129be612255565b020490565b51906001600160501b03821682036106ea57565b604051633fabe5a360e21b81529060a090829060049082906001600160a01b03165afa908115612a75575b600091612a29575b506000811315612a175790565b60405163fd1ee34960e01b8152600490fd5b9060a0823d8211612a6d575b81612a4260a09383611f01565b810103126109205750612a54816129c3565b50612a666080602083015192016129c3565b5038612a0a565b3d9150612a35565b612a7d611fb0565b612a02565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa918215612afd575b600092612add575b506000908152600260205260409020546001600160801b031690818110612282570390565b612af691925060203d81116127ac5761279d8183611f01565b9038612ab8565b612b05611fb0565b612ab0565b600082128015600160ff1b8401831216612b34575b6001600160ff1b038301821316612282570390565b612b3c612255565b612b1f565b6000811280156001600160ff1b03839003841316612b6d575b600160ff1b8290038312166122d6570190565b612b75612255565b612b5a565b610b7d612b85612170565b612ba8612ba36123196001549364ffffffffff8560d01c169061226c565b612520565b90604051926370a0823160e01b845260208480612bc8306004830161079c565b03817f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58316001600160a01b03165afa938415612c9d575b600094612c65575b5091612c59612c53612c5393612c4c612c5f9666038d7ea4c680009260018060401b0384612c3f8260018060681b03941684861661229a565b0497169160681c1661229a565b0495612caa565b91612caa565b90612b0a565b90612b41565b612c5f93919450612c53612c5393612c4c612c90612c599460203d81116127ac5761279d8183611f01565b9794965050935050612c06565b612ca5611fb0565b612bfe565b6001600160ff1b038111612cbb5790565b60405163e7e828ad60e01b8152600490fd5b60ff6001911660ff81146122d6570190565b612cf4612ced826005610b80565b54600c0b90565b6000918282600c0b1215612f1e57612d1b612d10826005610b80565b5460e81c61ffff1690565b612d39612d33612d2c846005610b80565b5460f81c90565b93612f5d565b612d98612d657f000000000000000000000000880d36763bb470cd395b7d6c76b50446fa70ace56129d7565b6001600160401b03927f00000000000000000000000000000000000000000000000000000000000f424084169190613329565b93612da1611f31565b5060ff927f00000000000000000000000000000000000000000000000000000000000000098416875b8186821610612ddf5750505050505050121590565b612dea84828561340f565b612dfd575b612df890612ccd565b612dca565b9688811215612f1057612e0f88611fbd565b612e26610afb612e20835160ff1690565b60ff1690565b612ee257608081019086612e3a8351610da0565b1615612ed65791612c5f612ec9612ece93612ec3612ebe612eb7612df8988f612e7f612e6a612e84926006610b80565b60208401516001600160a01b03165b90610b80565b610ba3565b90612ea86060612ea0610e9c604085015160018060a01b031690565b920151610da0565b916001600160801b0316613309565b9251610da0565b610da0565b906132cb565b612caa565b979050612def565b505096612df890612ccd565b60200151612f0c906001600160a01b0316604051637050033f60e01b81529182916004830161079c565b0390fd5b505050505050505050600190565b505050600190565b600c0b6001600160671b03198114612f3f575b60000390565b612f47612255565b612f39565b600160ff1b8114612f3f5760000390565b6000600c82900b12612f9d57600054610b7d9166038d7ea4c6800091612f97916001600160401b03909116906001600160681b031661229a565b04612caa565b612fcd612ec9610b7d92612fbe60018060401b0360005460401c1691612f26565b6001600160681b03169061281d565b612f4c565b6020906001600160401b038111612feb575b60051b0190565b612ff3611eea565b612fe4565b9061300282612fd2565b61300f6040519182611f01565b8281528092613020601f1991612fd2565b0190602036910137565b50634e487b7160e01b600052603260045260246000fd5b6020918151811015613056575b60051b010190565b61305e61302a565b61304e565b90613072612ced836005610b80565b916000918284600c0b121561324a5760ff92837f000000000000000000000000000000000000000000000000000000000000000916906130b182612ff8565b906130c0612d10866005610b80565b936130cf612d2c876005610b80565b916131026130fc7f000000000000000000000000880d36763bb470cd395b7d6c76b50446fa70ace56129d7565b99612f5d565b6001600160401b03939061313b907f00000000000000000000000000000000000000000000000000000000000f42408616908c90613329565b96613144611f31565b50825b8a8116888110156132385761315d84838561340f565b613171575b5061316c90612ccd565b613147565b848a929a1215613227576131848a611fbd565b60a08101918c896131958551610da0565b16156132195761321293612ec3612ebe612eb78e87612ea86060613209612c5f9a61320361316c9f9d6131f0612ec99d6131de610e9c6040612e7f95015160018060a01b031690565b6131e8868c613041565b526006610b80565b60208801516001600160a01b0316612e79565b95613041565b51920151610da0565b9890613162565b505050509761316c90612ccd565b505050509450945050935050929190565b50505050949350945050935012929190565b919250508190606090565b80546001600160f81b031660f89290921b6001600160f81b031916919091179055565b60009015610b7d5750600190565b60085460181c600162ffffff8093161b1616151590565b60085460301c600162ffffff8093161b1616151590565b60085460481c600162ffffff8093161b1616151590565b670de0b6b3a7640000916128199161229a565b612807907f00000000000000000000000000000000000000000000000000000000000f42409061229a565b906133139161229a565b6001600160401b03909116908115612811570490565b919061333490612caa565b6000808413939082136001600160ff1b038582168482048411166133f0575b600160ff1b956000851291859183168589058312166133e3575b600085129384168289058612166133d6575b0583129116166133c9575b6001600160401b039092169291029082156133bc575b81146000198314166133b0570590565b6133b8612255565b0590565b6133c46127f0565b6133a0565b6133d1612255565b61338a565b6133de612255565b61337f565b6133eb612255565b61336d565b6133f8612255565b613353565b60ff9182169116818110612282570390565b9060ff16916010831060001461342e5750600161ffff921b1616151590565b90506018821061343f575050600090565b600160ff8093600f1901161b1616151590565b6001600160401b039182169116818110612282570390565b805461ffff60e81b191660e89290921b61ffff60e81b16919091179055565b81518154602084015160408501516001600160e81b03199092166001600160681b039093169290921760689290921b600160681b600160a81b03169190911760a89190911b600160a81b600160e81b03161781556060820151610e429260ff91608091906134fb9061ffff168561346a565b01511690613255565b61361390610e42936135178451600c0b90565b600c82900b855260009182918683600c83900b811361362a5761359c6135756135e294613566612ebe6135c3966135606020612ea0612448995460018060401b039060801c1690565b90613452565b906001600160681b031661229a565b7f00000000000000000000000000000000000000000000000000038d7ea4c6800090612807565b7f000000000000000000000000000000000000000000000000000000000000000190612807565b6135d560408901916124578351610da0565b6001600160401b03169052565b600c0b12613618575461360c9060801c6001600160401b03165b6001600160401b03166020850152565b6005610b80565b613489565b546136259060c01c6135fc565b61360c565b61359c613575613665946136606123d361228e61365a612ebe6135c3996135606020612ea06124489c5460c01c90565b93612f26565b61229a565b6135e2565b92916001805460f81c16611da5576136896136853386611ead565b1590565b611072576001600160a01b038181167f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831909116036136fa575060088054166136e957610e429260001983036137ff5791506136e3816150d7565b916137ff565b6040516230dad960e61b8152600490fd5b9060046008949394541661371a57613714610e429461372c565b92613d74565b60405163b4abb28d60e01b8152600490fd5b6001600160801b0390818111613740571690565b60405163762ea71160e11b8152600490fd5b60008051602061517f83398151915260018154146137705760019055565b60405163139b643560e21b8152600490fd5b6001600160681b03918216919081169082900381116122d6570190565b80546001600160681b0319166001600160681b03909216919091179055565b6001600160681b039182169116818110612282570390565b8054600160681b600160d01b03191660689290921b600160681b600160d01b0316919091179055565b61382e6138ac9293827f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831613b50565b6138366122f1565b6138b961384c613847866005610b80565b612199565b8051600c0b906138b361387c61387561387061386786612f5d565b612c5f89612caa565b61393e565b8094613ad4565b979061389c6138958a61389060015461228e565b613782565b600161379f565b6138a76001546122e2565b6137be565b60016137d6565b86613504565b6040519081526001600160a01b0393841693849216907fd1cf3d156d5f8f0d50f6c122ed609cec09d35c9b9fb3fff6ea0959134dae424e90602090a36001600160681b038116613907575050565b60008051602061515f83398151915261393961392960009361270e8554610da0565b6040519081529081906020820190565b0390a3565b6000811261396457600054610b7d9161395f916001600160401b03166139ed565b613a63565b6139c161395f610b7d9261398560018060401b0360005460401c1691612f4c565b6139aa826000199266038d7ea4c68000908085048211811515166139e0575b026125c1565b600181106139d3575b82156139c6575b0104613a3d565b612f26565b6139ce6127f0565b6139ba565b6139db612255565b6139b3565b6139e8612255565b6139a4565b90610b7d9166038d7ea4c68000908260001904821183151516613a30575b6001600160401b0316918215613a23575b0204613a3d565b613a2b6127f0565b613a1c565b613a38612255565b613a0b565b6001600160681b0390818111613a51571690565b604051630dc7925560e11b8152600490fd5b6001600160681b03166001600160671b038111613a8057600c0b90565b604051639369ae3560e01b8152600490fd5b600c91820b910b6000821280156001600160671b03198401831216613ac7575b6001600160671b038301821316612282570390565b613acf612255565b613ab2565b91909180600c0b83600c0b818112613b4357600012613b075750613af89192613a92565b6001600160681b031690600090565b600013613b2a57613b189192613a92565b6000916001600160681b039190911690565b613b3390612f26565b6001600160681b03908116921690565b5050509050600090600090565b6040516370a0823160e01b8082529390926020926001600160a01b03169190838580613b7f306004830161079c565b0381865afa948515613cbd575b600095613c9e575b50823b156106ea576040516323b872dd60e01b81526001600160a01b03919091166004820152306024820152604481019190915260008160648183865af18015613c91575b613c7c575b503d8015613c7357602014613bf257600080fd5b816000803e6000515b15613c615781610b7d9460405192839182528180613c1c306004830161079c565b03915afa918215613c54575b600092613c37575b50506125cd565b613c4d9250803d106127ac5761279d8183611f01565b3880613c30565b613c5c611fb0565b613c28565b60405163073d1efd60e51b8152600490fd5b50600019613bfb565b8061175c6000613c8b93611f01565b38613bde565b613c99611fb0565b613bd9565b613cb6919550843d86116127ac5761279d8183611f01565b9338613b94565b613cc5611fb0565b613b8c565b90604051613cd9604082611f01565b91546001600160801b038116835260801c6020830152565b6001600160801b03918216919081169082900381116122d6570190565b80546001600160801b0319166001600160801b03909216919091179055565b90602060018060801b0391613d458382511685613d0e565b0151825490911660809190911b6001600160801b031916179055565b6001600160801b03909116815260200190565b919092613d80826120ec565b805160ff16613d8e8161329d565b613eca5750613d9c856121e4565b6001600160801b0391613dbb90613db69084168686613b50565b61372c565b92613dcf613dca826002610b80565b613cca565b92613df3613de686613de18751610b97565b613cf1565b6001600160801b03168552565b613dfd8451610b97565b90613e0e611d0d60e0860151610b97565b911611613eb857613e93613e8185613eb394613e8d7ffa56f7b24f17183d81894d3ac2ee654e3c26388d17a28dbd9549b8114304e1f497613e8887613e628e613e6e613e67612e7f85613e62856006610b80565b610b80565b9889613cf1565b988995613e7c856002610b80565b613d2d565b6006610b80565b613d0e565b89613ee7565b6040516001600160a01b0391821696821695909116939091829182613d61565b0390a4565b604051637ac7b99d60e11b8152600490fd5b6040516335d1e86560e11b815260ff919091166004820152602490fd5b909290916001600160801b03908116158080614048575b15613fa457505050613f11825160ff1690565b60ff81166010811015613f63575050613f4b613f43613f34610e42945160ff1690565b600160ff9091161b61ffff1690565b916005610b80565b90613f5c825461ffff9060e81c1690565b179061346a565b601891935010613f71575050565b613f91613f43613f856010610e42956133fd565b600160ff9182161b1690565b90613f9d825460f81c90565b1790613255565b15918261403d575b5050613fb6575050565b815160ff16806010811015613ffe575050613fe6613f43613fde613f34610e42955160ff1690565b1961ffff1690565b90613ff7825461ffff9060e81c1690565b169061346a565b60189193501061400c575050565b61402a613f43614023613f856010610e42966133fd565b1960ff1690565b90614036825460f81c90565b1690613255565b161590503880613fac565b508183161515613efe565b939293600260015460f81c16611da5576136856140709183611ead565b611072576001600160a01b038181168382161461410557807f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e583116908516146000146140d457610e42935060001983036141175791506140ce82615079565b91614117565b9192906040600854166140f3576140ed610e429461372c565b92614489565b604051630ecd760560e01b8152600490fd5b60405163e397a99b60e01b8152600490fd5b9190916141226122f1565b61412d816005610b80565b61413690612199565b614141846005610b80565b61414a90612199565b91815161415790600c0b90565b92805161416490600c0b90565b9261416e85612f5d565b61417787612caa565b61418091612b0a565b9561418a85612f5d565b9061419490612caa565b61419d91612b41565b906141a78761393e565b6141b1819361393e565b9687936141bd91614424565b976141c89197613ad4565b9787896001546141d79061228e565b906141e191613782565b906141eb916137be565b6141f690600161379f565b600154614202906122e2565b9061420c91613782565b90614216916137be565b6142219060016137d6565b61422b9185613504565b6142359187613504565b60009384811215614400576020600854166143ee5761425390612f4c565b7f0000000000000000000000000000000000000000000000000000000000000001116143dc5761428561368582612cdf565b6143ca57835460015466038d7ea4c68000906142d3906001600160681b036142af888284166137be565b6001600160401b03906142c49087831661281d565b9560401c169160681c1661229a565b0490801515918261439c575b505061438a5783905b6001600160681b0392808416614343575b505050811661430757505050565b61393961432760008051602061515f8339815191529261270e8554610da0565b6040519081526001600160a01b03909416939081906020820190565b61437f61436360008051602061515f8339815191529261270e8654610da0565b6040519081526001600160a01b03909316929081906020820190565b0390a38238806142f9565b60405163e012b19360e01b8152600490fd5b671bc16d674ec800009250906143bd670de0b6b3a76400006143c29361229a565b612807565b1138806142df565b604051630a62fbdb60e11b8152600490fd5b604051637139da2360e11b8152600490fd5b604051634f49eff560e11b8152600490fd5b506010600854166144125783906142e8565b60405163192efc2360e21b8152600490fd5b919082600c0b81600c0b818113613b43576000136144475750613af89192613a92565b60001261445857613b189192613a92565b61446190612f26565b6001600160681b03928316921690565b6001600160801b039182169116818110612282570390565b9192909261449f612e7f82613e62866006610b80565b6144b1612e7f83613e62886006610b80565b6144bb8483614471565b916144c68583613cf1565b926144da81613e8887613e628b6006610b80565b6144ed84613e8887613e628c6006610b80565b6144f6856120ec565b91614502835160ff1690565b61450e60ff82166132b4565b614592575061453d94939291614537916145278a6121e4565b6145308b6121e4565b838a613ee7565b87613ee7565b61454961368584612cdf565b6143ca576040516001600160a01b0391821694821693909116917f29db89d45e1a802b4d55e202984fce9faf1d30aedf86503ff1ea0ed9ebb6420191908190613eb39082613d61565b60405163460d2b4f60e01b815260ff919091166004820152602490fd5b939293600460015460f81c16611da5576136856145cc9183611ead565b611072576001600160a01b038481167f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58319091160361462357610e429350600019830361465457915061461d82615079565b91614654565b9192906080600854166146425761463c610e429461372c565b926148c1565b604051631e16772b60e01b8152600490fd5b90916138ac926146626122f1565b614670613847846005610b80565b6146ca61467e8251600c0b90565b61469361468a82612f5d565b612c5987612caa565b926138b36146aa6146a38661393e565b8094614424565b6146bf613895836138a760019e959e5461228e565b6138906001546122e2565b60008112156147e0576002600854166147ce576146e690612f4c565b7f0000000000000000000000000000000000000000000000000000000000000001116143dc5761471861368584612cdf565b6143ca57671bc16d674ec8000061472d612949565b1161438a575b61475e82827f000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831614819565b6040519182526001600160a01b0392831692169082907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90602090a36001600160681b0382166147ac575050565b60008051602061515f83398151915261393961392960009461270e8654610da0565b604051635088313560e11b8152600490fd5b5060016008541615614733576040516325964bab60e11b8152600490fd5b6001600160a01b039091168152602081019190915260400190565b6001600160a01b03169291833b156106ea5761485390604051809581809563a9059cbb60e01b8252600098899687968793600484016147fe565b03925af180156148b4575b6148a4575b503d9050801561489957602014614878575080fd5b90602081803e515b1561488757565b60405163cefaffeb60e01b8152600490fd5b509050600019614880565b6148ad91611f01565b3882614863565b6148bc611fb0565b61485e565b919290926148ce836121e4565b6148e0612e7f82613e62866006610b80565b6148ea8382614471565b906149126148f9846002610b80565b61490c866149078354610b97565b614471565b90613d0e565b61492582613e8885613e62896006610b80565b61492e836120ec565b805160ff1661493c81613286565b61499757509061494d929186613ee7565b61495961368584612cdf565b6143ca577fd6d480d5b3068db003533b170d67561494d72e3bf9fa40a266471351ebba9e1690613eb390613e936001600160801b0385168783614819565b604051630db276b560e01b815260ff919091166004820152602490fd5b91908110156149c45760051b0190565b612ff361302a565b35610b7d816106d9565b906040516149e5608082611f01565b915463ffffffff81168352602081811c6001600160401b031690840152606081811c6001600160801b0316604085015260e09190911c90830152565b60019063ffffffff8091169081146122d6570190565b9291909260016008815460f81c16611da5575a94614a536122f1565b60005b848110614b4d57505050614af890614af1614ad2613db6614a7c610e4297985a906125cd565b614acb614ab9614a95614a90886007610b80565b6149d6565b98612448614aaf614aaa8c5163ffffffff1690565b614a21565b63ffffffff168b52565b6135d560208a01916124578351610da0565b489061229a565b614ae46040860191613de18351610b97565b6001600160801b03169052565b6007610b80565b815160208084015160408501516060958601516001600160e01b031960e09190911b16600160601b600160e01b039190961b1663ffffffff909316600160201b600160601b039190921b161717919091179055565b80614b6b614b65614b60869489876149b4565b6149cc565b86614b71565b01614a56565b90614b7b81613063565b9192909215614efa57614b92613847826005610b80565b92614b9e8451600c0b90565b614ba781612f5d565b606086015161ffff16608087015160ff1695614bc1611f31565b50600096875b60ff7f00000000000000000000000000000000000000000000000000000000000000091660ff821610614d7c5750505050614c3b614c35612ec9856143bd60018060401b037f00000000000000000000000000000000000000000000000000000000000f424016809a61229a565b82612b41565b9160008312614d73575b614c4e8361393e565b9687614c5a9187613504565b614c65856005610b80565b6000614c709161346a565b86614c7c866005610b80565b6000614c8791613255565b614c9091613ad4565b600154614c9c9061228e565b90614ca691613782565b614cb190600161379f565b600154614cbd906122e2565b90614cc7916137be565b614cd29060016137d6565b614cdb91612b0a565b614ce490614f35565b92614cef9184613309565b6040805193845260208401919091526001600160a01b039182169485939216917f1547a878dc89ad3c367b6338b4be6a65a5dd74fb77ae044da1e8747ef1f4f62f9190a380600c0b600012614d42575050565b60008051602061515f833981519152613939613929600093614d6d614d678654610da0565b91614f0c565b9061281d565b60009250614c45565b614d8782828661340f565b614d9a575b60010160ff16925b92614bc7565b878b614da583611fbd565b60c08101516001600160401b0390614dbc90610da0565b1615614eeb57602081015183906001600160a01b03169c8d80600681614de28683610b80565b90614dec91610b80565b614df590610ba3565b94614dff91610b80565b90614e0991610b80565b6000614e1491613d0e565b614e1f906002610b80565b828154614e2b90610b97565b90614e3591614471565b614e3e91613d0e565b614e4b60ff871689613041565b516060840151614e5a90610da0565b614e6d916001600160801b038516613309565b9260c00151614e7b90610da0565b614e8490610da0565b614e8e90846132cb565b614e97916125c1565b604080516001600160801b0393909316835260208301939093529c6001600160a01b039081169481169316917f9850ab1af75177e4a9201c65a2cf7976d5d28e40ef63494b44366f86b2f9412e91a4614d8c565b50505060010160ff1692614d94565b604051636ef5bcdd60e11b8152600490fd5b600081600c0b12614f23576001600160681b031690565b60405163363b64b760e11b8152600490fd5b60008112614f235790565b610b7d91614f50614fc9926120ec565b6040810151614f67906001600160a01b03166129d7565b60c08201519091906001600160401b0390811680614ff0575b5050614fc3612ebe6060614fbb6143bd95966136607f000000000000000000000000880d36763bb470cd395b7d6c76b50446fa70ace56129d7565b930151610da0565b9061229a565b7f00000000000000000000000000000000000000000000000000000000000f424090612807565b6060614fbb614fc3936150556143bd97612ebe95615044670de0b6b3a764000094828693841061506c575b8303167f0000000000000000000000000000000000000000000000000853a0d2313c000061229a565b0480841061505f575b83039061229a565b0495505050614f80565b615067612255565b61504d565b615074612255565b61501b565b61509c615084612170565b61083964ffffffffff918260015460d01c169061226c565b506001600160a01b03909116600090815260056020526040812054600c0b9190808313156150d15750614d6d610b7d92614f0c565b91505090565b6150e2615084612170565b6001600160a01b03909216600090815260056020526040812054600c0b929150808312156150d15750614d6d61511a610b7d93612f26565b614f0c565b50600036818037808036817f0000000000000000000000000d4bd55a755134950027ce1f43190a354e648e205af43d82803e1561515a573d90f35b3d90fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc98c7730ba19013824f711a9ab74801459b27e6ff7685cb924587c89aeda53aca26469706673582212208b5b38d54ee250e2991d5501396c297bd513e3288a62f62831cc572d55212c0364736f6c634300080f0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"github_repository_metadata":null,"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":[[["0x3fB4d38ea7EC20D91917c09591490Eeda38Cf88A","0x78E6317DD6D43DdbDa00Dce32C2CbaFc99361a9d","0xaf88d065e77c8cC2239327C5EDb3A432268e5831","0x880D36763Bb470cd395B7d6c76b50446FA70ACe5","0x0d4Bd55A755134950027cE1F43190A354e648e20","900000000000000000","36000000000000000","3196000000000000000","0","900000000000000000","27778000000000000","3600000000000000000","15000000000000000","600000000000000000","1000000000000000","0","0","10000000000","1","5000000000000",[["0x912CE59144191C1204E64559FE8253a0e49E6548","0x5998a5C516bD5E479E0B6aa6F243d372730B68d2","18","700000000000000000","800000000000000000","900000000000000000","1946834000000000000000000"],["0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a","0xDB98056FecFff59D032aB628337A4887110df3dB","18","600000000000000000","750000000000000000","850000000000000000","2596000000000000000000"],["0x82aF49447D8a07e3bd95BD0d56f35241523fBab1","0xb2988bDAdc45c43e3fE1A728F715E94bee4DB406","18","830000000000000000","880000000000000000","930000000000000000","40000000000000000000000"],["0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f","0xcc392d2c3b37520e01712320bE331D41F7661013","8","750000000000000000","850000000000000000","900000000000000000","100000000000"],["0x5979D7b546E38E414F7E9822514be443A4800529","0x92014e7f331dFaB2848A5872AA8b2E7b6f3cE8B4","18","800000000000000000","850000000000000000","900000000000000000","8000000000000000000000"],["0x2416092f143378750bb29b79eD961ab195CcEea5","0x5Eba6Ec97843163C92Ab48a7aC0CCc8423c652b1","18","800000000000000000","850000000000000000","900000000000000000","102000000000000000000"],["0x57F5E098CaD7A3D1Eed53991D4d66C45C9AF7812","0x5D173813B4505701e79E654b36A95E6c1FAD4448","18","0","100000000000000","1000000000000000000","0"],["0xd09ACb80C1E8f2291862c4978A008791c9167003","0x5372Bcf3486D59C23F5fC85745B41F180EFFf881","18","800000000000000000","850000000000000000","900000000000000000","0"],["0x6c84a8f1c29108F47a79964b5Fe888D4f4D0dE40","0xE808488e8627F6531bA79a13A9E0271B39abEb1C","18","800000000000000000","850000000000000000","900000000000000000","0"]]],{"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"}]],"compiler_version":"v0.8.15+commit.e14f2714","is_verified_via_verifier_alliance":false,"verified_at":"2026-08-19T19:25:44.057062Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6103a0806040523462000a915762005cf3803803809162000021828562000aac565b8339602082828101031262000a915781516001600160401b03811162000a91576102a0818401838501031262000a915760405192620000636102a08562000aac565b6200007082820162000ad0565b84526200008260208383010162000ad0565b60208501526200009760408383010162000ad0565b6040850152620000ac60608383010162000ad0565b6060850152620000c160808383010162000ad0565b6080850152620000d660a08383010162000ae5565b60a0850152620000eb60c08383010162000ae5565b60c08501526200010060e08383010162000ae5565b60e0850152620001166101008383010162000ae5565b6101008501526200012d6101208383010162000ae5565b610120850152620001446101408383010162000ae5565b6101408501526200015b6101608383010162000ae5565b610160850152620001726101808383010162000ae5565b610180850152620001896101a08383010162000ae5565b6101a0850152620001a06101c08383010162000ae5565b6101c0850152620001b76101e08383010162000ae5565b6101e0850152620001ce6102008383010162000ae5565b610200850152620001e56102208383010162000afa565b610220850152620001fc6102408383010162000afa565b610240850152620002136102608383010162000afa565b6102608501528082016102800151926001600160401b03841162000a9157808201601f858585010101121562000a9157818301840151916001600160401b03831162000a9657604051946200026f60208560051b018762000aac565b8386526020860194838301602060e08702848487010101011162000a9157828101820160200195915b602060e08702828487010101018710620009d35761028089018890526040808a0151905163313ce56760e01b81528a91602090829060049082906001600160a01b03165afa908115620008245760009162000991575b50601260ff82161162000902576101a0820151670de0b6b3a76400006001600160401b03909116116200097f57601861028083015151116200096d576102208201516001600160681b0316156200095b57606082015160405163313ce56760e01b815290602090829060049082906001600160a01b03165afa908115620008245760009162000914575b5060ff6008911603620009025781516001600160a01b0390811660809081526020840151821660a0526040840151821660c0526060840151821660e05283015116610100526101a08201516001600160401b039081166102205261032082905260ff909116600a0a81166102408190526101c083015190911661026052620f42401162000902576102408051620f42409004610360526102208201516001600160681b039081166102c0526101e0808401516001600160401b039081166102809081526102008087015183166102a0529486015184166102e0526102608601519093166103005260a0850151811661012090815260c08601516301e13380908316819004831661014090815260e088015184168290048416610160908152610100808a015186168490048616610180908152948a015186166101a05291890151851683900485166101c0528801518416829004841690945290860151821604169092528201515160ff166103405251604051630e085c5b60e31b81529190602090839060049082906001600160a01b03165afa9182156200082457600092620008b8575b50610280015190604051809263ba15b9d160e01b82526024820160206004840152815180915260206044840192019060005b8181106200083057506020949284900392849250600091506001600160a01b03165af19081156200082457600091620007df575b50610380526040516151d462000b1f82396080518181816107c601528181610f81015281816116e80152611b6f015260a051818181610a2a0152611087015260c0518181816109d001528181611667015281816118a901528181611bd801528181611c900152818161273601528181612bcc0152818161369a0152818161380a0152818161408a015281816145dd015261473a015260e051818181611df101528181612d41015281816130d80152614f970152610100518181816110c7015261512c01526101205181818161161501526126020152610140518181816111b00152818161263e01526126a90152610160518181816112e301526126d50152610180518181816114670152818161266501526127c301526101a0518181816113ef015261285801526101c051818181610c380152818161289401526128ff01526101e051818181610b35015261292501526102005181818161125f01526128bb01526102205181818161093c0152615020015261024051818181610f0101528181612d7001528181613112015281816132e401528181614c0e0152614fcb0152610260518181816116a7015261357701526102805181818161087a015261249701526102a0518181816114d9015261241f01526102c05181818161142b015261239101526102e051818181610cb20152818161425501526146e8015261030051818181610d2d0152611d7e01526103205181610cf00152610340518181816115d8015281816120ff01528181612da7015281816130870152614bcb0152610360518161359e015261038051818181611b140152611fe801526151d490f35b6020813d6020116200081b575b81620007fb6020938362000aac565b81010312620008175762000810915062000ad0565b8162000582565b5080fd5b3d9150620007ec565b6040513d6000823e3d90fd5b825180516001600160a01b0390811686526020828101519091168187015260408083015160ff16908701526060808301516001600160401b039081169188019190915260808084015182169088015260a0808401519091169087015260c0918201516001600160801b03169186019190915287955060e090940193909201916001016200054e565b90916020823d602011620008f9575b81620008d66020938362000aac565b81010312620008f65750620008ee6102809162000ad0565b91906200051c565b80fd5b3d9150620008c7565b604051630456c65960e51b8152600490fd5b906020823d60201162000952575b81620009316020938362000aac565b81010312620008f6575060ff6200094a60089262000b0f565b915062000378565b3d915062000922565b604051636e77247560e01b8152600490fd5b60405163df8153c760e01b8152600490fd5b6040516324dc918f60e11b8152600490fd5b906020823d602011620009ca575b81620009ae6020938362000aac565b81010312620008f65750620009c39062000b0f565b82620002ee565b3d91506200099f565b60e087868601031262000a915760405192620009f160e08562000aac565b620009fc8862000ad0565b845262000a0c6020890162000ad0565b602085015262000a1f6040890162000b0f565b604085015262000a326060890162000ae5565b606085015262000a456080890162000ae5565b608085015262000a5860a0890162000ae5565b60a085015260c0880151936001600160801b038516850362000a9157602060e09282829760c08695015281520198019793505062000298565b600080fd5b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b0382119082101762000a9657604052565b51906001600160a01b038216820362000a9157565b51906001600160401b038216820362000a9157565b51906001600160681b038216820362000a9157565b519060ff8216820362000a915756fe60806040526004361015610018575b61001661511f565b005b60003560e01c8063042e02cf146106d05780630546e6ec146106c75780630902f1ac146106be5780630bc47ad1146106b55780630c340a24146106ac57806318160ddd146106a3578063189bb2f11461069a5780631c9f7fb9146106915780631f5954bd14610688578063214435621461067f57806323b872dd1461067657806324a3d6221461066d578063264413181461066457806329c5a1a01461065b5780632a48cf12146106525780632b92a07d146106495780632d05670b146106405780632e04b8e714610637578063300e6beb1461062e578063313ce5671461062557806332176c491461061c578063374c49b41461061357806338aa813f1461060a5780633b3bec2e1461060157806341976e09146105f85780634232cd63146105ef578063439e2e45146105e657806344c1e5eb146105dd57806344c35d07146105d457806344ff241d146105cb5780634a95a76a146105c257806350a1efea146105b957806359e017bd146105b05780635a94b8d1146105a757806367800b5f1461059e5780636f678cce1461059557806370a082311461058c5780637914acc7146105835780637ac88ed11461057a5780637eb7113114610571578063804de71f146105685780638285ef401461055f5780638a5704df146105565780638d5d814c1461054d57806390323177146105445780639241a5611461053b5780639364e18a1461053257806394920cca146105295780639545e4de146105205780639ae3890c146105175780639ea99a5a1461050e5780639fa83b5a146105055780639ff567f8146104fc578063a1654379146104f3578063a1a1ef43146104ea578063a46fe83b146104e1578063a5b4ff79146104d8578063a9059cbb146104cf578063aba7f15e146104c6578063ad14777c146104bd578063b2a7a721146104b4578063bfe69c8d146104ab578063c04a5b06146104a2578063c1ee2c1814610499578063c3b35a7e14610490578063c3cecfd214610487578063c55dae631461047e578063c5fa15cf14610475578063c82643b41461046c578063c8c7fe6b14610463578063cde680411461045a578063cdfadab614610451578063ce26a7b014610448578063d8e5f6111461043f578063d955759d14610436578063dc4abafd1461042d578063e1066c9014610424578063e30ca4041461041b578063e372f03a14610412578063e478795d14610409578063e4e6e77914610400578063e719dc74146103f7578063e7dad6bd146103ee578063f2b9fdb8146103e5578063f3fef3a3146103dc5763fddc530f0361000e576103d7611e89565b61000e565b506103d7611e54565b506103d7611e20565b506103d7611dda565b506103d7611db7565b506103d7611c2e565b506103d7611b43565b506103d7611afd565b506103d7611ad9565b506103d7611ab2565b506103d7611a3f565b506103d7611a20565b506103d76119f9565b506103d76119d5565b506103d76119ba565b506103d761199e565b506103d7611975565b506103d7611946565b506103d76118d8565b506103d7611892565b506103d761182d565b506103d7611809565b506103d76117e3565b506103d76117bc565b506103d7611796565b506103d761176f565b506103d76116ca565b506103d761168e565b506103d7611638565b506103d76115fc565b506103d76115bd565b506103d7611596565b506103d7611555565b506103d761152d565b506103d76114fc565b506103d76114c0565b506103d76114a5565b506103d761148a565b506103d761144e565b506103d7611412565b506103d76113d6565b506103d76113b1565b506103d761138a565b506103d7611367565b506103d7611306565b506103d76112ca565b506103d76112ae565b506103d7611282565b506103d7611246565b506103d761121e565b506103d76111fa565b506103d76111d3565b506103d7611197565b506103d7611141565b506103d761111d565b506103d76110f6565b506103d76110b0565b506103d7610f31565b506103d7610ee8565b506103d7610ec4565b506103d7610ea1565b506103d7610e79565b506103d7610e44565b506103d7610d78565b506103d7610d50565b506103d7610d14565b506103d7610cd5565b506103d7610c99565b506103d7610c5b565b506103d7610c1f565b506103d7610bca565b506103d7610b1c565b506103d7610ae5565b506103d7610a90565b506103d7610a13565b506103d76109b0565b506103d761095f565b506103d7610923565b506103d761089d565b506103d7610861565b506103d76107f5565b506103d76107af565b506103d7610776565b506103d7610752565b506103d761072e565b506103d76106ef565b6001600160a01b038116036106ea57565b600080fd5b50346106ea5760203660031901126106ea576020610717600435610712816106d9565b613063565b50506040519015158152f35b60009103126106ea57565b50346106ea5760003660031901126106ea5760206080600854161515604051908152f35b50346106ea5760003660031901126106ea57602061076e612b7a565b604051908152f35b50346106ea5760003660031901126106ea5760206001805460f81c161515604051908152f35b6001600160a01b03909116815260200190565b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760003660031901126106ea57602066038d7ea4c6800061085861081c612170565b61083f6001549161083964ffffffffff91828560d01c169061226c565b16612520565b506001600160401b0316906001600160681b031661229a565b04604051908152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576000806003193601126109205760015464ffffffffff8160d01c1661090f5764ffffffffff60d01b6108d3612170565b64ffffffffff60d01b1990921660d09290921b161760015580546001600160801b0319166e038d7ea4c6800000038d7ea4c68000178155604051f35b60405162dc149f60e41b8152600490fd5b80fd5b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea5760206001600854161515604051908152f35b908160609103126106ea578035610999816106d9565b91604060208301356109aa816106d9565b92013590565b50346106ea576109f66109c4366004610983565b91906109ce613752565b7f00000000000000000000000000000000000000000000000000000000000000009133614053565b600060008051602061517f83398151915255602060405160018152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b91908260809103126106ea578135610a70816106d9565b916020810135610a7f816106d9565b91606060408301356109aa816106d9565b50346106ea57610ab6610aa4366004610a59565b92610ab0929192613752565b336145af565b600060008051602061517f83398151915255005b908160209103126106ea573562ffffff811681036106ea5790565b50346106ea576020610b12610afb366004610aca565b60085460601c600162ffffff8093161b1616151590565b6040519015158152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b91908260409103126106ea5760208235610b71816106d9565b920135610b7d816106d9565b90565b9060018060a01b0316600052602052604060002090565b6001600160801b031690565b546001600160801b031690565b6001600160801b0391821681529116602082015260400190565b50346106ea57610c1b610bff610be1366004610b58565b6001600160a01b039091166000908152600660205260409020610b80565b54604051918291608081901c906001600160801b031683610bb0565b0390f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760203660031901126106ea57600435610c79816106d9565b60018060a01b031660005260046020526020604060002054604051908152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760203660031901126106ea57602061076e600435610d73816106d9565b6150d7565b50346106ea5760203660031901126106ea576020610b12600435610d9b816106d9565b612cdf565b6001600160401b031690565b610e429092919260e08061010083019560ff815116845260018060a01b03806020830151166020860152604082015116604085015260018060401b036060820151166060850152610e0c6080820151608086019060018060401b03169052565b60a0818101516001600160401b03169085015260c0818101516001600160401b03169085015201516001600160801b0316910152565b565b50346106ea5760203660031901126106ea57610c1b610e6d600435610e68816106d9565b6120ec565b60405191829182610dac565b50346106ea5760203660031901126106ea57602061076e600435610e9c816106d9565b6129d7565b50346106ea57610ab6610eb5366004610983565b91610ebe613752565b3361366a565b50346106ea57610ab6610ed8366004610983565b91610ee1613752565b3333614053565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b359081151582036106ea57565b50346106ea5760a03660031901126106ea57610f4d6004610f24565b610f576024610f24565b610f616044610f24565b91610f6c6064610f24565b92610f776084610f24565b60018060a01b03807f0000000000000000000000000000000000000000000000000000000000000000163314159081611083575b50611072577f3be39979091ae7ca962aa1c44e645f2df3c221b79f324afa5f44aedc8d2f690d9461106d92611038610ff56000610fe788613278565b9060ff8080931691161b1690565b6110036001610fe78a613278565b176110126002610fe785613278565b176110216003610fe786613278565b176110306004610fe787613278565b176001613255565b6040519586958693909594919260809360a0860197151586521515602086015215156040850152151560608401521515910152565b0390a1005b6040516282b42960e81b8152600490fd5b90507f00000000000000000000000000000000000000000000000000000000000000001633141538610fab565b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760003660031901126106ea57602062ffffff60085460601c16604051908152f35b50346106ea5760003660031901126106ea576020604051671bc16d674ec800008152f35b50346106ea5760203660031901126106ea5760043561115f816106d9565b6001600160a01b031660009081526002602052604090819020549051908190610c1b90608081901c906001600160801b031683610bb0565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea576020600460015460f81c161515604051908152f35b50346106ea5760003660031901126106ea5760206040600854161515604051908152f35b50346106ea5760203660031901126106ea57602061076e600435611241816106d9565b615079565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760403660031901126106ea57602061076e6004356112a5816106d9565b60243590614f40565b50346106ea5760003660031901126106ea57602061076e612949565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea57602066038d7ea4c6800061085861132d612170565b61134a6001549161083964ffffffffff91828560d01c169061226c565b6001600160401b03169160681c6001600160681b0316905061229a565b50346106ea5760003660031901126106ea57602060088054161515604051908152f35b50346106ea5760003660031901126106ea576020600860015460f81c161515604051908152f35b50346106ea57610ab66113c5366004610a59565b926113d1929192613752565b61366a565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576020610b126114a0366004610aca565b6132b4565b50346106ea576020610b126114bb366004610aca565b61329d565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760203660031901126106ea57602061151b600435612842565b6040516001600160401b039091168152f35b50346106ea5760203660031901126106ea57602061076e600435611550816106d9565b612a82565b50346106ea57602060ff61158a61156d366004610b58565b6001600160a01b0390911660009081526003855260409020610b80565b54166040519015158152f35b50346106ea5760003660031901126106ea576020600260015460f81c161515604051908152f35b50346106ea5760003660031901126106ea57602060405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea5760403660031901126106ea576109f6600435611659816106d9565b611661613752565b602435907f0000000000000000000000000000000000000000000000000000000000000000903333614053565b50346106ea5760003660031901126106ea5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b50346106ea576116db366004610983565b91906001600160a01b03907f000000000000000000000000000000000000000000000000000000000000000082163303611072571691823b156106ea5761173c926000928360405180968195829463095ea7b360e01b8452600484016147fe565b03925af18015611762575b61174d57005b8061175c600061001693611f01565b80610723565b61176a611fb0565b611747565b50346106ea5760003660031901126106ea57602062ffffff60085460181c16604051908152f35b50346106ea5760203660031901126106ea576100166004356117b7816106d9565b6121e4565b50346106ea5760003660031901126106ea57602062ffffff60085460301c16604051908152f35b50346106ea57610ab66117f7366004610a59565b92611803929192613752565b33614053565b50346106ea57610ab661181d366004610983565b91611826613752565b33336145af565b50346106ea5760403660031901126106ea5760043561184b816106d9565b602435906001600160401b03908183116106ea57366023840112156106ea5782600401359182116106ea573660248360051b850101116106ea576024610016930190614a37565b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760203660031901126106ea576004356118f6816106d9565b60018060a01b0316600052600760205260806040600020546040519063ffffffff8116825260018060401b038160201c166020830152600180841b038160601c16604083015260e01c6060820152f35b50346106ea5760003660031901126106ea5760206010600854161515604051908152f35b60ff8116036106ea57565b50346106ea5760203660031901126106ea57610c1b610e6d6004356119998161196a565b611fbd565b50346106ea576020610b126119b4366004610b58565b90611ead565b50346106ea576020610b126119d0366004610aca565b613286565b50346106ea5760003660031901126106ea5760206002600854161515604051908152f35b50346106ea5760003660031901126106ea576020601060015460f81c161515604051908152f35b50346106ea5760203660031901126106ea57602061151b6004356125d8565b50346106ea5760203660031901126106ea57600435611a5d816106d9565b60018060a01b0316600052600560205260a06040600020546040519080600c0b825260018060401b03808260681c1660208401528160a81c16604083015261ffff8160e81c16606083015260f81c6080820152f35b50346106ea5760003660031901126106ea57602062ffffff60085460481c16604051908152f35b50346106ea5760003660031901126106ea57602062ffffff60085416604051908152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760403660031901126106ea57600435611b61816106d9565b602435906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116330361107257611b9e612b7a565b60008112908115611c1c575b50611c0a5781611bfc847fec4431f2ba1a9382f6b0c4352b888cba6f7db91667d9f776abe5ad8ddc5401b6947f0000000000000000000000000000000000000000000000000000000000000000614819565b6040519384521691602090a2005b60405163128bd24d60e31b8152600490fd5b611c269150614f35565b831138611baa565b50346106ea5760803660031901126106ea57600435611c4c816106d9565b60643590611c59826106d9565b611c61613752565b601060015460f81c16611da557611c76612b7a565b60008112159081611d7a575b50611d6857611cb4604435337f0000000000000000000000000000000000000000000000000000000000000000613b50565b90611cbf8282614f40565b926024358410611d5657611cd282612a82565b8411611c0a577ff891b2a411b0e66a5f0a6ff1368670fefa287a13f541eb633a386a1a9cc7046b91611d19611d3c92611d12611d0d8861372c565b610b97565b9083614819565b6040805194855260208501959095526001600160a01b0316933393918291820190565b0390a3610016600060008051602061517f83398151915255565b60405163fa6ad35560e01b8152600490fd5b604051631d99ddbf60e01b8152600490fd5b90507f0000000000000000000000000000000000000000000000000000000000000000111538611c82565b6040516313d0ff5960e31b8152600490fd5b50346106ea5760003660031901126106ea57602080600854161515604051908152f35b50346106ea5760003660031901126106ea576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b50346106ea5760403660031901126106ea57610ab6600435611e41816106d9565b611e49613752565b60243590333361366a565b50346106ea5760403660031901126106ea57610ab6600435611e75816106d9565b611e7d613752565b602435903333336145af565b50346106ea5760003660031901126106ea5760206004600854161515604051908152f35b6001600160a01b03808316911690811491908215611eca57505090565b60ff925090611ee59160005260036020526040600020610b80565b541690565b50634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017611f2457604052565b611f2c611eea565b604052565b60405190611f4161010083611f01565b8160e06000918281528260208201528260408201528260608201528260808201528260a08201528260c08201520152565b5190610e428261196a565b5190610e42826106d9565b51906001600160401b03821682036106ea57565b51906001600160801b03821682036106ea57565b506040513d6000823e3d90fd5b611fc5611f31565b5060405163c8c7fe6b60e01b815260ff91909116600482015261010080826024817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9182156120df575b60009261202657505090565b90918282813d83116120d8575b61203d8183611f01565b81010312610920575060e06120d0916120596040519485611f01565b61206281611f72565b845261207060208201611f7d565b602085015261208160408201611f7d565b604085015261209260608201611f88565b60608501526120a360808201611f88565b60808501526120b460a08201611f88565b60a08501526120c560c08201611f88565b60c085015201611f9c565b60e082015290565b503d612033565b6120e7611fb0565b61201a565b906120f5611f31565b5060009060ff92837f000000000000000000000000000000000000000000000000000000000000000016925b838582161061213c57604051633640530560e01b8152600490fd5b61214581611fbd565b60208101516001600160a01b0384811691161461216757506001018416612121565b93505050915090565b600160281b4210156121875764ffffffffff421690565b604051633d32ffdb60e01b8152600490fd5b906040516121a860a082611f01565b608081935480600c0b835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c910152565b610e42906121f06122f1565b60018060a01b038116600052600560205260406000206040519061221560a083611f01565b549182600c0b9283835260018060401b03808260681c1660208501528160a81c16604084015261ffff8160e81c16606084015260f81c6080830152613504565b50634e487b7160e01b600052601160045260246000fd5b64ffffffffff9182169116818110612282570390565b61228a612255565b0390565b6001600160681b031690565b80600019048211811515166122ad570290565b6122b5612255565b0290565b6001600160401b03918216919081169082900381116122d6570190565b6122de612255565b0190565b60681c6001600160681b031690565b6122f9612170565b61232361231961231360015464ffffffffff9060d01c1690565b8361226c565b64ffffffffff1690565b908161232d575050565b8161238461233d610e4294612520565b60008054600160401b600160801b03191660409290921b600160401b600160801b0316919091178155919082546001600160401b0319166001600160401b03909116178255565b61238f60015461228e565b7f000000000000000000000000000000000000000000000000000000000000000092906001600160681b031683811015612484575b506123d86123d36001546122e2565b61228e565b9283101561240c575b50506001805464ffffffffff60d01b191660d09390931b64ffffffffff60d01b169290921790915550565b61244d61244861247c9461244361245c947f000000000000000000000000000000000000000000000000000000000000000061229a565b6132de565b6124fa565b825460c01c6122b9565b6122b9565b81546001600160c01b031660c09190911b6001600160c01b031916179055565b3880806123e1565b6124ce6124bb6124486124f493612443867f000000000000000000000000000000000000000000000000000000000000000061229a565b845460801c6001600160401b03166122b9565b8354600160801b600160c01b03191660809190911b600160801b600160c01b0316178355565b386123c4565b6001600160401b039081811161250e571690565b6040516372a1cb5160e11b8152600490fd5b6000546001600160401b03604082901c81169392918116919081612545575b50509190565b8161259861259261257297946125a46125aa9761259e8761257961259e9961256b612949565b9e8f6125d8565b169d612842565b169b612598612592670de0b6b3a7640000998a9361229a565b8461229a565b046124fa565b906122b9565b9861229a565b91388061253f565b908160209103126106ea575190565b811981116122d6570190565b818110612282570390565b6125e360015461228e565b6001600160681b038116156127e9578115806127c0575b6126ff575b507f00000000000000000000000000000000000000000000000000000000000000008082116126895750612448670de0b6b3a7640000612662610b7d937f000000000000000000000000000000000000000000000000000000000000000061229a565b047f00000000000000000000000000000000000000000000000000000000000000006125c1565b610b7d916126f96126d3836126cd670de0b6b3a7640000612662612448977f000000000000000000000000000000000000000000000000000000000000000061229a565b936125cd565b7f00000000000000000000000000000000000000000000000000000000000000006132cb565b906125c1565b6127139061270e600054610da0565b61281d565b6040516370a0823160e01b81529060208280612732306004830161079c565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9182156127b3575b600092612783575b50101561277d57386125ff565b50600090565b6127a591925060203d81116127ac575b61279d8183611f01565b8101906125b2565b9038612770565b503d612793565b6127bb611fb0565b612768565b507f000000000000000000000000000000000000000000000000000000000000000015156125fa565b5050600090565b50634e487b7160e01b600052601260045260246000fd5b8115612811570490565b6128196127f0565b0490565b66038d7ea4c6800091612819916001600160401b0316906001600160681b031661229a565b60015460681c6001600160681b03161561277d577f00000000000000000000000000000000000000000000000000000000000000008082116128df5750612448670de0b6b3a76400006128b8610b7d937f000000000000000000000000000000000000000000000000000000000000000061229a565b047f00000000000000000000000000000000000000000000000000000000000000006125c1565b610b7d916126f9612923836126cd670de0b6b3a76400006128b8612448977f000000000000000000000000000000000000000000000000000000000000000061229a565b7f00000000000000000000000000000000000000000000000000000000000000006132cb565b60005460015466038d7ea4c680009061298b906001600160681b036001600160401b038461297b82881684861661229a565b049560401c169160681c1661229a565b0481612998575050600090565b670de0b6b3a76400009080600019048211811515166129b657020490565b6129be612255565b020490565b51906001600160501b03821682036106ea57565b604051633fabe5a360e21b81529060a090829060049082906001600160a01b03165afa908115612a75575b600091612a29575b506000811315612a175790565b60405163fd1ee34960e01b8152600490fd5b9060a0823d8211612a6d575b81612a4260a09383611f01565b810103126109205750612a54816129c3565b50612a666080602083015192016129c3565b5038612a0a565b3d9150612a35565b612a7d611fb0565b612a02565b6040516370a0823160e01b8152306004820152906001600160a01b0316602082602481845afa918215612afd575b600092612add575b506000908152600260205260409020546001600160801b031690818110612282570390565b612af691925060203d81116127ac5761279d8183611f01565b9038612ab8565b612b05611fb0565b612ab0565b600082128015600160ff1b8401831216612b34575b6001600160ff1b038301821316612282570390565b612b3c612255565b612b1f565b6000811280156001600160ff1b03839003841316612b6d575b600160ff1b8290038312166122d6570190565b612b75612255565b612b5a565b610b7d612b85612170565b612ba8612ba36123196001549364ffffffffff8560d01c169061226c565b612520565b90604051926370a0823160e01b845260208480612bc8306004830161079c565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa938415612c9d575b600094612c65575b5091612c59612c53612c5393612c4c612c5f9666038d7ea4c680009260018060401b0384612c3f8260018060681b03941684861661229a565b0497169160681c1661229a565b0495612caa565b91612caa565b90612b0a565b90612b41565b612c5f93919450612c53612c5393612c4c612c90612c599460203d81116127ac5761279d8183611f01565b9794965050935050612c06565b612ca5611fb0565b612bfe565b6001600160ff1b038111612cbb5790565b60405163e7e828ad60e01b8152600490fd5b60ff6001911660ff81146122d6570190565b612cf4612ced826005610b80565b54600c0b90565b6000918282600c0b1215612f1e57612d1b612d10826005610b80565b5460e81c61ffff1690565b612d39612d33612d2c846005610b80565b5460f81c90565b93612f5d565b612d98612d657f00000000000000000000000000000000000000000000000000000000000000006129d7565b6001600160401b03927f000000000000000000000000000000000000000000000000000000000000000084169190613329565b93612da1611f31565b5060ff927f00000000000000000000000000000000000000000000000000000000000000008416875b8186821610612ddf5750505050505050121590565b612dea84828561340f565b612dfd575b612df890612ccd565b612dca565b9688811215612f1057612e0f88611fbd565b612e26610afb612e20835160ff1690565b60ff1690565b612ee257608081019086612e3a8351610da0565b1615612ed65791612c5f612ec9612ece93612ec3612ebe612eb7612df8988f612e7f612e6a612e84926006610b80565b60208401516001600160a01b03165b90610b80565b610ba3565b90612ea86060612ea0610e9c604085015160018060a01b031690565b920151610da0565b916001600160801b0316613309565b9251610da0565b610da0565b906132cb565b612caa565b979050612def565b505096612df890612ccd565b60200151612f0c906001600160a01b0316604051637050033f60e01b81529182916004830161079c565b0390fd5b505050505050505050600190565b505050600190565b600c0b6001600160671b03198114612f3f575b60000390565b612f47612255565b612f39565b600160ff1b8114612f3f5760000390565b6000600c82900b12612f9d57600054610b7d9166038d7ea4c6800091612f97916001600160401b03909116906001600160681b031661229a565b04612caa565b612fcd612ec9610b7d92612fbe60018060401b0360005460401c1691612f26565b6001600160681b03169061281d565b612f4c565b6020906001600160401b038111612feb575b60051b0190565b612ff3611eea565b612fe4565b9061300282612fd2565b61300f6040519182611f01565b8281528092613020601f1991612fd2565b0190602036910137565b50634e487b7160e01b600052603260045260246000fd5b6020918151811015613056575b60051b010190565b61305e61302a565b61304e565b90613072612ced836005610b80565b916000918284600c0b121561324a5760ff92837f000000000000000000000000000000000000000000000000000000000000000016906130b182612ff8565b906130c0612d10866005610b80565b936130cf612d2c876005610b80565b916131026130fc7f00000000000000000000000000000000000000000000000000000000000000006129d7565b99612f5d565b6001600160401b03939061313b907f00000000000000000000000000000000000000000000000000000000000000008616908c90613329565b96613144611f31565b50825b8a8116888110156132385761315d84838561340f565b613171575b5061316c90612ccd565b613147565b848a929a1215613227576131848a611fbd565b60a08101918c896131958551610da0565b16156132195761321293612ec3612ebe612eb78e87612ea86060613209612c5f9a61320361316c9f9d6131f0612ec99d6131de610e9c6040612e7f95015160018060a01b031690565b6131e8868c613041565b526006610b80565b60208801516001600160a01b0316612e79565b95613041565b51920151610da0565b9890613162565b505050509761316c90612ccd565b505050509450945050935050929190565b50505050949350945050935012929190565b919250508190606090565b80546001600160f81b031660f89290921b6001600160f81b031916919091179055565b60009015610b7d5750600190565b60085460181c600162ffffff8093161b1616151590565b60085460301c600162ffffff8093161b1616151590565b60085460481c600162ffffff8093161b1616151590565b670de0b6b3a7640000916128199161229a565b612807907f00000000000000000000000000000000000000000000000000000000000000009061229a565b906133139161229a565b6001600160401b03909116908115612811570490565b919061333490612caa565b6000808413939082136001600160ff1b038582168482048411166133f0575b600160ff1b956000851291859183168589058312166133e3575b600085129384168289058612166133d6575b0583129116166133c9575b6001600160401b039092169291029082156133bc575b81146000198314166133b0570590565b6133b8612255565b0590565b6133c46127f0565b6133a0565b6133d1612255565b61338a565b6133de612255565b61337f565b6133eb612255565b61336d565b6133f8612255565b613353565b60ff9182169116818110612282570390565b9060ff16916010831060001461342e5750600161ffff921b1616151590565b90506018821061343f575050600090565b600160ff8093600f1901161b1616151590565b6001600160401b039182169116818110612282570390565b805461ffff60e81b191660e89290921b61ffff60e81b16919091179055565b81518154602084015160408501516001600160e81b03199092166001600160681b039093169290921760689290921b600160681b600160a81b03169190911760a89190911b600160a81b600160e81b03161781556060820151610e429260ff91608091906134fb9061ffff168561346a565b01511690613255565b61361390610e42936135178451600c0b90565b600c82900b855260009182918683600c83900b811361362a5761359c6135756135e294613566612ebe6135c3966135606020612ea0612448995460018060401b039060801c1690565b90613452565b906001600160681b031661229a565b7f000000000000000000000000000000000000000000000000000000000000000090612807565b7f000000000000000000000000000000000000000000000000000000000000000090612807565b6135d560408901916124578351610da0565b6001600160401b03169052565b600c0b12613618575461360c9060801c6001600160401b03165b6001600160401b03166020850152565b6005610b80565b613489565b546136259060c01c6135fc565b61360c565b61359c613575613665946136606123d361228e61365a612ebe6135c3996135606020612ea06124489c5460c01c90565b93612f26565b61229a565b6135e2565b92916001805460f81c16611da5576136896136853386611ead565b1590565b611072576001600160a01b038181167f0000000000000000000000000000000000000000000000000000000000000000909116036136fa575060088054166136e957610e429260001983036137ff5791506136e3816150d7565b916137ff565b6040516230dad960e61b8152600490fd5b9060046008949394541661371a57613714610e429461372c565b92613d74565b60405163b4abb28d60e01b8152600490fd5b6001600160801b0390818111613740571690565b60405163762ea71160e11b8152600490fd5b60008051602061517f83398151915260018154146137705760019055565b60405163139b643560e21b8152600490fd5b6001600160681b03918216919081169082900381116122d6570190565b80546001600160681b0319166001600160681b03909216919091179055565b6001600160681b039182169116818110612282570390565b8054600160681b600160d01b03191660689290921b600160681b600160d01b0316919091179055565b61382e6138ac9293827f0000000000000000000000000000000000000000000000000000000000000000613b50565b6138366122f1565b6138b961384c613847866005610b80565b612199565b8051600c0b906138b361387c61387561387061386786612f5d565b612c5f89612caa565b61393e565b8094613ad4565b979061389c6138958a61389060015461228e565b613782565b600161379f565b6138a76001546122e2565b6137be565b60016137d6565b86613504565b6040519081526001600160a01b0393841693849216907fd1cf3d156d5f8f0d50f6c122ed609cec09d35c9b9fb3fff6ea0959134dae424e90602090a36001600160681b038116613907575050565b60008051602061515f83398151915261393961392960009361270e8554610da0565b6040519081529081906020820190565b0390a3565b6000811261396457600054610b7d9161395f916001600160401b03166139ed565b613a63565b6139c161395f610b7d9261398560018060401b0360005460401c1691612f4c565b6139aa826000199266038d7ea4c68000908085048211811515166139e0575b026125c1565b600181106139d3575b82156139c6575b0104613a3d565b612f26565b6139ce6127f0565b6139ba565b6139db612255565b6139b3565b6139e8612255565b6139a4565b90610b7d9166038d7ea4c68000908260001904821183151516613a30575b6001600160401b0316918215613a23575b0204613a3d565b613a2b6127f0565b613a1c565b613a38612255565b613a0b565b6001600160681b0390818111613a51571690565b604051630dc7925560e11b8152600490fd5b6001600160681b03166001600160671b038111613a8057600c0b90565b604051639369ae3560e01b8152600490fd5b600c91820b910b6000821280156001600160671b03198401831216613ac7575b6001600160671b038301821316612282570390565b613acf612255565b613ab2565b91909180600c0b83600c0b818112613b4357600012613b075750613af89192613a92565b6001600160681b031690600090565b600013613b2a57613b189192613a92565b6000916001600160681b039190911690565b613b3390612f26565b6001600160681b03908116921690565b5050509050600090600090565b6040516370a0823160e01b8082529390926020926001600160a01b03169190838580613b7f306004830161079c565b0381865afa948515613cbd575b600095613c9e575b50823b156106ea576040516323b872dd60e01b81526001600160a01b03919091166004820152306024820152604481019190915260008160648183865af18015613c91575b613c7c575b503d8015613c7357602014613bf257600080fd5b816000803e6000515b15613c615781610b7d9460405192839182528180613c1c306004830161079c565b03915afa918215613c54575b600092613c37575b50506125cd565b613c4d9250803d106127ac5761279d8183611f01565b3880613c30565b613c5c611fb0565b613c28565b60405163073d1efd60e51b8152600490fd5b50600019613bfb565b8061175c6000613c8b93611f01565b38613bde565b613c99611fb0565b613bd9565b613cb6919550843d86116127ac5761279d8183611f01565b9338613b94565b613cc5611fb0565b613b8c565b90604051613cd9604082611f01565b91546001600160801b038116835260801c6020830152565b6001600160801b03918216919081169082900381116122d6570190565b80546001600160801b0319166001600160801b03909216919091179055565b90602060018060801b0391613d458382511685613d0e565b0151825490911660809190911b6001600160801b031916179055565b6001600160801b03909116815260200190565b919092613d80826120ec565b805160ff16613d8e8161329d565b613eca5750613d9c856121e4565b6001600160801b0391613dbb90613db69084168686613b50565b61372c565b92613dcf613dca826002610b80565b613cca565b92613df3613de686613de18751610b97565b613cf1565b6001600160801b03168552565b613dfd8451610b97565b90613e0e611d0d60e0860151610b97565b911611613eb857613e93613e8185613eb394613e8d7ffa56f7b24f17183d81894d3ac2ee654e3c26388d17a28dbd9549b8114304e1f497613e8887613e628e613e6e613e67612e7f85613e62856006610b80565b610b80565b9889613cf1565b988995613e7c856002610b80565b613d2d565b6006610b80565b613d0e565b89613ee7565b6040516001600160a01b0391821696821695909116939091829182613d61565b0390a4565b604051637ac7b99d60e11b8152600490fd5b6040516335d1e86560e11b815260ff919091166004820152602490fd5b909290916001600160801b03908116158080614048575b15613fa457505050613f11825160ff1690565b60ff81166010811015613f63575050613f4b613f43613f34610e42945160ff1690565b600160ff9091161b61ffff1690565b916005610b80565b90613f5c825461ffff9060e81c1690565b179061346a565b601891935010613f71575050565b613f91613f43613f856010610e42956133fd565b600160ff9182161b1690565b90613f9d825460f81c90565b1790613255565b15918261403d575b5050613fb6575050565b815160ff16806010811015613ffe575050613fe6613f43613fde613f34610e42955160ff1690565b1961ffff1690565b90613ff7825461ffff9060e81c1690565b169061346a565b60189193501061400c575050565b61402a613f43614023613f856010610e42966133fd565b1960ff1690565b90614036825460f81c90565b1690613255565b161590503880613fac565b508183161515613efe565b939293600260015460f81c16611da5576136856140709183611ead565b611072576001600160a01b038181168382161461410557807f000000000000000000000000000000000000000000000000000000000000000016908516146000146140d457610e42935060001983036141175791506140ce82615079565b91614117565b9192906040600854166140f3576140ed610e429461372c565b92614489565b604051630ecd760560e01b8152600490fd5b60405163e397a99b60e01b8152600490fd5b9190916141226122f1565b61412d816005610b80565b61413690612199565b614141846005610b80565b61414a90612199565b91815161415790600c0b90565b92805161416490600c0b90565b9261416e85612f5d565b61417787612caa565b61418091612b0a565b9561418a85612f5d565b9061419490612caa565b61419d91612b41565b906141a78761393e565b6141b1819361393e565b9687936141bd91614424565b976141c89197613ad4565b9787896001546141d79061228e565b906141e191613782565b906141eb916137be565b6141f690600161379f565b600154614202906122e2565b9061420c91613782565b90614216916137be565b6142219060016137d6565b61422b9185613504565b6142359187613504565b60009384811215614400576020600854166143ee5761425390612f4c565b7f0000000000000000000000000000000000000000000000000000000000000000116143dc5761428561368582612cdf565b6143ca57835460015466038d7ea4c68000906142d3906001600160681b036142af888284166137be565b6001600160401b03906142c49087831661281d565b9560401c169160681c1661229a565b0490801515918261439c575b505061438a5783905b6001600160681b0392808416614343575b505050811661430757505050565b61393961432760008051602061515f8339815191529261270e8554610da0565b6040519081526001600160a01b03909416939081906020820190565b61437f61436360008051602061515f8339815191529261270e8654610da0565b6040519081526001600160a01b03909316929081906020820190565b0390a38238806142f9565b60405163e012b19360e01b8152600490fd5b671bc16d674ec800009250906143bd670de0b6b3a76400006143c29361229a565b612807565b1138806142df565b604051630a62fbdb60e11b8152600490fd5b604051637139da2360e11b8152600490fd5b604051634f49eff560e11b8152600490fd5b506010600854166144125783906142e8565b60405163192efc2360e21b8152600490fd5b919082600c0b81600c0b818113613b43576000136144475750613af89192613a92565b60001261445857613b189192613a92565b61446190612f26565b6001600160681b03928316921690565b6001600160801b039182169116818110612282570390565b9192909261449f612e7f82613e62866006610b80565b6144b1612e7f83613e62886006610b80565b6144bb8483614471565b916144c68583613cf1565b926144da81613e8887613e628b6006610b80565b6144ed84613e8887613e628c6006610b80565b6144f6856120ec565b91614502835160ff1690565b61450e60ff82166132b4565b614592575061453d94939291614537916145278a6121e4565b6145308b6121e4565b838a613ee7565b87613ee7565b61454961368584612cdf565b6143ca576040516001600160a01b0391821694821693909116917f29db89d45e1a802b4d55e202984fce9faf1d30aedf86503ff1ea0ed9ebb6420191908190613eb39082613d61565b60405163460d2b4f60e01b815260ff919091166004820152602490fd5b939293600460015460f81c16611da5576136856145cc9183611ead565b611072576001600160a01b038481167f00000000000000000000000000000000000000000000000000000000000000009091160361462357610e429350600019830361465457915061461d82615079565b91614654565b9192906080600854166146425761463c610e429461372c565b926148c1565b604051631e16772b60e01b8152600490fd5b90916138ac926146626122f1565b614670613847846005610b80565b6146ca61467e8251600c0b90565b61469361468a82612f5d565b612c5987612caa565b926138b36146aa6146a38661393e565b8094614424565b6146bf613895836138a760019e959e5461228e565b6138906001546122e2565b60008112156147e0576002600854166147ce576146e690612f4c565b7f0000000000000000000000000000000000000000000000000000000000000000116143dc5761471861368584612cdf565b6143ca57671bc16d674ec8000061472d612949565b1161438a575b61475e82827f0000000000000000000000000000000000000000000000000000000000000000614819565b6040519182526001600160a01b0392831692169082907f9b1bfa7fa9ee420a16e124f794c35ac9f90472acc99140eb2f6447c714cad8eb90602090a36001600160681b0382166147ac575050565b60008051602061515f83398151915261393961392960009461270e8654610da0565b604051635088313560e11b8152600490fd5b5060016008541615614733576040516325964bab60e11b8152600490fd5b6001600160a01b039091168152602081019190915260400190565b6001600160a01b03169291833b156106ea5761485390604051809581809563a9059cbb60e01b8252600098899687968793600484016147fe565b03925af180156148b4575b6148a4575b503d9050801561489957602014614878575080fd5b90602081803e515b1561488757565b60405163cefaffeb60e01b8152600490fd5b509050600019614880565b6148ad91611f01565b3882614863565b6148bc611fb0565b61485e565b919290926148ce836121e4565b6148e0612e7f82613e62866006610b80565b6148ea8382614471565b906149126148f9846002610b80565b61490c866149078354610b97565b614471565b90613d0e565b61492582613e8885613e62896006610b80565b61492e836120ec565b805160ff1661493c81613286565b61499757509061494d929186613ee7565b61495961368584612cdf565b6143ca577fd6d480d5b3068db003533b170d67561494d72e3bf9fa40a266471351ebba9e1690613eb390613e936001600160801b0385168783614819565b604051630db276b560e01b815260ff919091166004820152602490fd5b91908110156149c45760051b0190565b612ff361302a565b35610b7d816106d9565b906040516149e5608082611f01565b915463ffffffff81168352602081811c6001600160401b031690840152606081811c6001600160801b0316604085015260e09190911c90830152565b60019063ffffffff8091169081146122d6570190565b9291909260016008815460f81c16611da5575a94614a536122f1565b60005b848110614b4d57505050614af890614af1614ad2613db6614a7c610e4297985a906125cd565b614acb614ab9614a95614a90886007610b80565b6149d6565b98612448614aaf614aaa8c5163ffffffff1690565b614a21565b63ffffffff168b52565b6135d560208a01916124578351610da0565b489061229a565b614ae46040860191613de18351610b97565b6001600160801b03169052565b6007610b80565b815160208084015160408501516060958601516001600160e01b031960e09190911b16600160601b600160e01b039190961b1663ffffffff909316600160201b600160601b039190921b161717919091179055565b80614b6b614b65614b60869489876149b4565b6149cc565b86614b71565b01614a56565b90614b7b81613063565b9192909215614efa57614b92613847826005610b80565b92614b9e8451600c0b90565b614ba781612f5d565b606086015161ffff16608087015160ff1695614bc1611f31565b50600096875b60ff7f00000000000000000000000000000000000000000000000000000000000000001660ff821610614d7c5750505050614c3b614c35612ec9856143bd60018060401b037f000000000000000000000000000000000000000000000000000000000000000016809a61229a565b82612b41565b9160008312614d73575b614c4e8361393e565b9687614c5a9187613504565b614c65856005610b80565b6000614c709161346a565b86614c7c866005610b80565b6000614c8791613255565b614c9091613ad4565b600154614c9c9061228e565b90614ca691613782565b614cb190600161379f565b600154614cbd906122e2565b90614cc7916137be565b614cd29060016137d6565b614cdb91612b0a565b614ce490614f35565b92614cef9184613309565b6040805193845260208401919091526001600160a01b039182169485939216917f1547a878dc89ad3c367b6338b4be6a65a5dd74fb77ae044da1e8747ef1f4f62f9190a380600c0b600012614d42575050565b60008051602061515f833981519152613939613929600093614d6d614d678654610da0565b91614f0c565b9061281d565b60009250614c45565b614d8782828661340f565b614d9a575b60010160ff16925b92614bc7565b878b614da583611fbd565b60c08101516001600160401b0390614dbc90610da0565b1615614eeb57602081015183906001600160a01b03169c8d80600681614de28683610b80565b90614dec91610b80565b614df590610ba3565b94614dff91610b80565b90614e0991610b80565b6000614e1491613d0e565b614e1f906002610b80565b828154614e2b90610b97565b90614e3591614471565b614e3e91613d0e565b614e4b60ff871689613041565b516060840151614e5a90610da0565b614e6d916001600160801b038516613309565b9260c00151614e7b90610da0565b614e8490610da0565b614e8e90846132cb565b614e97916125c1565b604080516001600160801b0393909316835260208301939093529c6001600160a01b039081169481169316917f9850ab1af75177e4a9201c65a2cf7976d5d28e40ef63494b44366f86b2f9412e91a4614d8c565b50505060010160ff1692614d94565b604051636ef5bcdd60e11b8152600490fd5b600081600c0b12614f23576001600160681b031690565b60405163363b64b760e11b8152600490fd5b60008112614f235790565b610b7d91614f50614fc9926120ec565b6040810151614f67906001600160a01b03166129d7565b60c08201519091906001600160401b0390811680614ff0575b5050614fc3612ebe6060614fbb6143bd95966136607f00000000000000000000000000000000000000000000000000000000000000006129d7565b930151610da0565b9061229a565b7f000000000000000000000000000000000000000000000000000000000000000090612807565b6060614fbb614fc3936150556143bd97612ebe95615044670de0b6b3a764000094828693841061506c575b8303167f000000000000000000000000000000000000000000000000000000000000000061229a565b0480841061505f575b83039061229a565b0495505050614f80565b615067612255565b61504d565b615074612255565b61501b565b61509c615084612170565b61083964ffffffffff918260015460d01c169061226c565b506001600160a01b03909116600090815260056020526040812054600c0b9190808313156150d15750614d6d610b7d92614f0c565b91505090565b6150e2615084612170565b6001600160a01b03909216600090815260056020526040812054600c0b929150808312156150d15750614d6d61511a610b7d93612f26565b614f0c565b50600036818037808036817f00000000000000000000000000000000000000000000000000000000000000005af43d82803e1561515a573d90f35b3d90fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efc98c7730ba19013824f711a9ab74801459b27e6ff7685cb924587c89aeda53aca26469706673582212208b5b38d54ee250e2991d5501396c297bd513e3288a62f62831cc572d55212c0364736f6c634300080f003300000000000000000000000000000000000000000000000000000000000000200000000000000000000000003fb4d38ea7ec20d91917c09591490eeda38cf88a00000000000000000000000078e6317dd6d43ddbda00dce32c2cbafc99361a9d000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000880d36763bb470cd395b7d6c76b50446fa70ace50000000000000000000000000d4bd55a755134950027ce1f43190a354e648e200000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000007fe5cf2bea00000000000000000000000000000000000000000000000000002c5a79111e26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000000062aff19e92200000000000000000000000000000000000000000000000000031f5c4ed2768000000000000000000000000000000000000000000000000000000354a6ba7a180000000000000000000000000000000000000000000000000000853a0d2313c000000000000000000000000000000000000000000000000000000038d7ea4c680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000048c2739500000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000009000000000000000000000000912ce59144191c1204e64559fe8253a0e49e65480000000000000000000000005998a5c516bd5e479e0b6aa6f243d372730b68d2000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000009b6e64a8ec600000000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000019c4215262765a0080000000000000000000000000000fc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a000000000000000000000000db98056fecfff59d032ab628337a4887110df3db00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000853a0d2313c00000000000000000000000000000000000000000000000000000a688906bd8b00000000000000000000000000000000000000000000000000000bcbce7f1b15000000000000000000000000000000000000000000000000008cbabcb5cd7210000000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000b2988bdadc45c43e3fe1a728f715e94bee4db40600000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b84c09a3b9300000000000000000000000000000000000000000000000000000c3663566a5800000000000000000000000000000000000000000000000000000ce80612991d0000000000000000000000000000000000000000000000000878678326eac90000000000000000000000000000002f2a2543b76a4166549f7aab2e75bef0aefc5b0f000000000000000000000000cc392d2c3b37520e01712320be331d41f766101300000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000a688906bd8b00000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000000000174876e8000000000000000000000000005979d7b546e38e414f7e9822514be443a480052900000000000000000000000092014e7f331dfab2848a5872aa8b2e7b6f3ce8b400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000001b1ae4d6e2ef50000000000000000000000000000002416092f143378750bb29b79ed961ab195cceea50000000000000000000000005eba6ec97843163c92ab48a7ac0ccc8423c652b100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000058788cb94b1d8000000000000000000000000000057f5e098cad7a3d1eed53991d4d66c45c9af78120000000000000000000000005d173813b4505701e79e654b36a95e6c1fad44480000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005af3107a40000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d09acb80c1e8f2291862c4978a008791c91670030000000000000000000000005372bcf3486d59c23f5fc85745b41f180efff88100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c84a8f1c29108f47a79964b5fe888d4f4d0de40000000000000000000000000e808488e8627f6531ba79a13a9e0271b39abeb1c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000000000000000000000","name":"CometWithExtendedAssetList","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"default","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"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/vendor/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"},{"file_path":"contracts/test/Comp.sol","source_code":"pragma solidity 0.8.15;\npragma experimental ABIEncoderV2;\n\ncontract Comp {\n    /// @notice EIP-20 token name for this token\n    string public constant name = \"Compound\";\n\n    /// @notice EIP-20 token symbol for this token\n    string public constant symbol = \"COMP\";\n\n    /// @notice EIP-20 token decimals for this token\n    uint8 public constant decimals = 18;\n\n    /// @notice Total number of tokens in circulation\n    uint public constant totalSupply = 10000000e18; // 10 million Comp\n\n    /// @notice Allowance amounts on behalf of others\n    mapping (address => mapping (address => uint96)) internal allowances;\n\n    /// @notice Official record of token balances for each account\n    mapping (address => uint96) internal balances;\n\n    /// @notice A record of each accounts delegate\n    mapping (address => address) public delegates;\n\n    /// @notice A checkpoint for marking number of votes from a given block\n    struct Checkpoint {\n        uint32 fromBlock;\n        uint96 votes;\n    }\n\n    /// @notice A record of votes checkpoints for each account, by index\n    mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;\n\n    /// @notice The number of checkpoints for each account\n    mapping (address => uint32) public numCheckpoints;\n\n    /// @notice The EIP-712 typehash for the contract's domain\n    bytes32 public constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n    /// @notice The EIP-712 typehash for the delegation struct used by the contract\n    bytes32 public constant DELEGATION_TYPEHASH = keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n    /// @notice A record of states for signing / validating signatures\n    mapping (address => uint) public nonces;\n\n    /// @notice An event thats emitted when an account changes its delegate\n    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n    /// @notice An event thats emitted when a delegate account's vote balance changes\n    event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\n\n    /// @notice The standard EIP-20 transfer event\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n\n    /// @notice The standard EIP-20 approval event\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n    /**\n     * @notice Construct a new Comp token\n     * @param account The initial account to grant all the tokens\n     */\n    constructor(address account) {\n        balances[account] = uint96(totalSupply);\n        emit Transfer(address(0), account, totalSupply);\n    }\n\n    /**\n     * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\n     * @param account The address of the account holding the funds\n     * @param spender The address of the account spending the funds\n     * @return The number of tokens approved\n     */\n    function allowance(address account, address spender) external view returns (uint) {\n        return allowances[account][spender];\n    }\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 rawAmount The number of tokens that are approved (2^256-1 means infinite)\n     * @return Whether or not the approval succeeded\n     */\n    function approve(address spender, uint rawAmount) external returns (bool) {\n        uint96 amount;\n        if (rawAmount == type(uint256).max) {\n            amount = type(uint96).max;\n        } else {\n            amount = safe96(rawAmount, \"Comp::approve: amount exceeds 96 bits\");\n        }\n\n        allowances[msg.sender][spender] = amount;\n\n        emit Approval(msg.sender, spender, amount);\n        return true;\n    }\n\n    /**\n     * @notice Get the number of tokens held by the `account`\n     * @param account The address of the account to get the balance of\n     * @return The number of tokens held\n     */\n    function balanceOf(address account) external view returns (uint) {\n        return balances[account];\n    }\n\n    /**\n     * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n     * @param dst The address of the destination account\n     * @param rawAmount The number of tokens to transfer\n     * @return Whether or not the transfer succeeded\n     */\n    function transfer(address dst, uint rawAmount) external returns (bool) {\n        uint96 amount = safe96(rawAmount, \"Comp::transfer: amount exceeds 96 bits\");\n        _transferTokens(msg.sender, dst, amount);\n        return true;\n    }\n\n    /**\n     * @notice Transfer `amount` tokens from `src` to `dst`\n     * @param src The address of the source account\n     * @param dst The address of the destination account\n     * @param rawAmount The number of tokens to transfer\n     * @return Whether or not the transfer succeeded\n     */\n    function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {\n        address spender = msg.sender;\n        uint96 spenderAllowance = allowances[src][spender];\n        uint96 amount = safe96(rawAmount, \"Comp::approve: amount exceeds 96 bits\");\n\n        if (spender != src && spenderAllowance != type(uint96).max) {\n            uint96 newAllowance = sub96(spenderAllowance, amount, \"Comp::transferFrom: transfer amount exceeds spender allowance\");\n            allowances[src][spender] = newAllowance;\n\n            emit Approval(src, spender, newAllowance);\n        }\n\n        _transferTokens(src, dst, amount);\n        return true;\n    }\n\n    /**\n     * @notice Delegate votes from `msg.sender` to `delegatee`\n     * @param delegatee The address to delegate votes to\n     */\n    function delegate(address delegatee) public {\n        return _delegate(msg.sender, delegatee);\n    }\n\n    /**\n     * @notice Delegates votes from signatory to `delegatee`\n     * @param delegatee The address to delegate votes to\n     * @param nonce The contract state required to match the signature\n     * @param expiry The time at which to expire the signature\n     * @param v The recovery byte of the signature\n     * @param r Half of the ECDSA signature pair\n     * @param s Half of the ECDSA signature pair\n     */\n    function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {\n        bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));\n        bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n        bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n        address signatory = ecrecover(digest, v, r, s);\n        require(signatory != address(0), \"Comp::delegateBySig: invalid signature\");\n        require(nonce == nonces[signatory]++, \"Comp::delegateBySig: invalid nonce\");\n        require(block.timestamp <= expiry, \"Comp::delegateBySig: signature expired\");\n        return _delegate(signatory, delegatee);\n    }\n\n    /**\n     * @notice Gets the current votes balance for `account`\n     * @param account The address to get votes balance\n     * @return The number of current votes for `account`\n     */\n    function getCurrentVotes(address account) external view returns (uint96) {\n        uint32 nCheckpoints = numCheckpoints[account];\n        return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;\n    }\n\n    /**\n     * @notice Determine the prior number of votes for an account as of a block number\n     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n     * @param account The address of the account to check\n     * @param blockNumber The block number to get the vote balance at\n     * @return The number of votes the account had as of the given block\n     */\n    function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {\n        require(blockNumber < block.number, \"Comp::getPriorVotes: not yet determined\");\n\n        uint32 nCheckpoints = numCheckpoints[account];\n        if (nCheckpoints == 0) {\n            return 0;\n        }\n\n        // First check most recent balance\n        if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {\n            return checkpoints[account][nCheckpoints - 1].votes;\n        }\n\n        // Next check implicit zero balance\n        if (checkpoints[account][0].fromBlock > blockNumber) {\n            return 0;\n        }\n\n        uint32 lower = 0;\n        uint32 upper = nCheckpoints - 1;\n        while (upper > lower) {\n            uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow\n            Checkpoint memory cp = checkpoints[account][center];\n            if (cp.fromBlock == blockNumber) {\n                return cp.votes;\n            } else if (cp.fromBlock < blockNumber) {\n                lower = center;\n            } else {\n                upper = center - 1;\n            }\n        }\n        return checkpoints[account][lower].votes;\n    }\n\n    function _delegate(address delegator, address delegatee) internal {\n        address currentDelegate = delegates[delegator];\n        uint96 delegatorBalance = balances[delegator];\n        delegates[delegator] = delegatee;\n\n        emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n        _moveDelegates(currentDelegate, delegatee, delegatorBalance);\n    }\n\n    function _transferTokens(address src, address dst, uint96 amount) internal {\n        require(src != address(0), \"Comp::_transferTokens: cannot transfer from the zero address\");\n        require(dst != address(0), \"Comp::_transferTokens: cannot transfer to the zero address\");\n\n        balances[src] = sub96(balances[src], amount, \"Comp::_transferTokens: transfer amount exceeds balance\");\n        balances[dst] = add96(balances[dst], amount, \"Comp::_transferTokens: transfer amount overflows\");\n        emit Transfer(src, dst, amount);\n\n        _moveDelegates(delegates[src], delegates[dst], amount);\n    }\n\n    function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {\n        if (srcRep != dstRep && amount > 0) {\n            if (srcRep != address(0)) {\n                uint32 srcRepNum = numCheckpoints[srcRep];\n                uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;\n                uint96 srcRepNew = sub96(srcRepOld, amount, \"Comp::_moveVotes: vote amount underflows\");\n                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);\n            }\n\n            if (dstRep != address(0)) {\n                uint32 dstRepNum = numCheckpoints[dstRep];\n                uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;\n                uint96 dstRepNew = add96(dstRepOld, amount, \"Comp::_moveVotes: vote amount overflows\");\n                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);\n            }\n        }\n    }\n\n    function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {\n      uint32 blockNumber = safe32(block.number, \"Comp::_writeCheckpoint: block number exceeds 32 bits\");\n\n      if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {\n          checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n      } else {\n          checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\n          numCheckpoints[delegatee] = nCheckpoints + 1;\n      }\n\n      emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n    }\n\n    function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n        require(n < 2**32, errorMessage);\n        return uint32(n);\n    }\n\n    function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {\n        require(n < 2**96, errorMessage);\n        return uint96(n);\n    }\n\n    function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n        uint96 c = a + b;\n        require(c >= a, errorMessage);\n        return c;\n    }\n\n    function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {\n        require(b <= a, errorMessage);\n        return a - b;\n    }\n\n    function getChainId() internal view returns (uint) {\n        uint256 chainId;\n        assembly { chainId := chainid() }\n        return chainId;\n    }\n}"},{"file_path":"contracts/Create2DeployerInterface.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.9;\n\ninterface ICreate2Deployer {\n    /**\n     * @dev Deploys a contract using `CREATE2`.\n     * @param value Amount of ETH to send with the contract creation.\n     * @param salt A unique salt used to compute the deployment address.\n     * @param code The bytecode of the contract to deploy.\n     */\n    function deploy(uint256 value, bytes32 salt, bytes memory code) external;\n\n    /**\n     * @dev Returns the address where a contract will be stored if deployed via `deploy`.\n     * @param salt A unique salt used to compute the deployment address.\n     * @param codeHash The keccak256 hash of the contract bytecode.\n     */\n    function computeAddress(bytes32 salt, bytes32 codeHash) external view returns (address);\n}\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/pricefeeds/RsETHScalingPriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../vendor/kelp/ILRTOracle.sol\";\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title Scaling price feed for rsETH\n * @notice A custom price feed that scales up or down the price received from an underlying Kelp price feed and returns the result\n * @author Compound\n */\ncontract RsETHScalingPriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error InvalidInt256();\n    error BadDecimals();\n\n    /// @notice Version of the price feed\n    uint public constant VERSION = 1;\n\n    /// @notice Description of the price feed\n    string public description;\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Underlying Kelp price feed where prices are fetched from\n    address public immutable underlyingPriceFeed;\n\n    /// @notice Whether or not the price should be upscaled\n    bool internal immutable shouldUpscale;\n\n    /// @notice The amount to upscale or downscale the price by\n    int256 internal immutable rescaleFactor;\n\n    /**\n     * @notice Construct a new scaling price feed\n     * @param underlyingPriceFeed_ The address of the underlying price feed to fetch prices from\n     * @param decimals_ The number of decimals for the returned prices\n     **/\n    constructor(address underlyingPriceFeed_, uint8 decimals_, string memory description_) {\n        underlyingPriceFeed = underlyingPriceFeed_;\n        if (decimals_ > 18) revert BadDecimals();\n        decimals = decimals_;\n        description = description_;\n\n        uint8 underlyingPriceFeedDecimals = 18;\n        // Note: Solidity does not allow setting immutables in if/else statements\n        shouldUpscale = underlyingPriceFeedDecimals < decimals_ ? true : false;\n        rescaleFactor = (shouldUpscale\n            ? signed256(10 ** (decimals_ - underlyingPriceFeedDecimals))\n            : signed256(10 ** (underlyingPriceFeedDecimals - decimals_))\n        );\n    }\n\n    /**\n     * @notice Price for the latest round\n     * @return roundId Round id from the underlying price feed\n     * @return answer Latest price for the asset in terms of ETH\n     * @return startedAt Timestamp when the round was started; passed on from underlying price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from underlying price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed\n     **/\n    function latestRoundData() override external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        int256 price = signed256(ILRTOracle(underlyingPriceFeed).rsETHPrice());\n        return (1, scalePrice(price), block.timestamp, block.timestamp, 1);\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 scalePrice(int256 price) internal view returns (int256) {\n        int256 scaledPrice;\n        if (shouldUpscale) {\n            scaledPrice = price * rescaleFactor;\n        } else {\n            scaledPrice = price / rescaleFactor;\n        }\n        return scaledPrice;\n    }\n    \n    /**\n     * @notice Current version of the price feed\n     * @return The version of the price feed contract\n     **/\n    function version() external pure returns (uint256) {\n        return VERSION;\n    }\n}"},{"file_path":"contracts/IWstETH.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./ERC20.sol\";\n\n/**\n * @dev Interface for interacting with WstETH contract\n * Note Not a comprehensive interface\n */\ninterface IWstETH is ERC20 {\n    function stETH() external returns (address);\n\n    function wrap(uint256 _stETHAmount) external returns (uint256);\n    function unwrap(uint256 _wstETHAmount) external returns (uint256);\n\n    function receive() external payable;\n\n    function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256);\n    function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256);\n\n    function stEthPerToken() external view returns (uint256);\n    function tokensPerStEth() external view returns (uint256);\n}"},{"file_path":"contracts/test/NonStandardFaucetFeeToken.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../IERC20NonStandard.sol\";\n\n/**\n * @title Non-standard ERC20 token\n * @dev Implementation of the basic standard token.\n *  See https://github.com/ethereum/EIPs/issues/20\n * @dev With USDT fee token mechanism\n * @dev Note: `transfer` and `transferFrom` do not return a boolean\n */\ncontract NonStandardFeeToken is IERC20NonStandard {\n    string public name;\n    string public symbol;\n    uint8 public decimals;\n    address public owner;\n    uint256 public totalSupply;\n    mapping(address => mapping (address => uint256)) public allowance;\n    mapping(address => uint256) public balanceOf;\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n    event Params(uint feeBasisPoints, uint maxFee);\n\n    // additional variables for use if transaction fees ever became necessary\n    uint public basisPointsRate = 0;\n    uint public maximumFee = 0;\n\n    constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n        totalSupply = _initialAmount;\n        balanceOf[msg.sender] = _initialAmount;\n        name = _tokenName;\n        symbol = _tokenSymbol;\n        decimals = _decimalUnits;\n    }\n\n    function transfer(address dst, uint256 amount) external virtual {\n        require(amount <= balanceOf[msg.sender], \"ERC20: transfer amount exceeds balance\");\n        uint256 fee = amount * basisPointsRate / 10000;\n        uint256 sendAmount = amount - fee;\n        if (fee > maximumFee) {\n            fee = maximumFee;\n        }\n\n        // For testing purpose, just forward fee to contract itself\n        if (fee > 0) {\n            balanceOf[address(this)] = balanceOf[address(this)] + fee;\n        }\n\n        balanceOf[msg.sender] = balanceOf[msg.sender] - amount;\n        balanceOf[dst] = balanceOf[dst] + sendAmount;\n        emit Transfer(msg.sender, dst, sendAmount);\n    }\n\n    function transferFrom(address src, address dst, uint256 amount) external virtual {\n        require(amount <= allowance[src][msg.sender], \"ERC20: transfer amount exceeds allowance\");\n        require(amount <= balanceOf[src], \"ERC20: transfer amount exceeds balance\");\n        uint256 fee = amount * basisPointsRate / 10000;\n        uint256 sendAmount = amount - fee;\n        if (fee > maximumFee) {\n            fee = maximumFee;\n        }\n\n        // For testing purpose, just forward fee to contract itself\n        if (fee > 0) {\n            balanceOf[address(this)] = balanceOf[address(this)] + fee;\n        }\n\n        allowance[src][msg.sender] = allowance[src][msg.sender] - amount;\n        balanceOf[src] = balanceOf[src] - amount;\n        balanceOf[dst] = balanceOf[dst] + sendAmount;\n        emit Transfer(src, dst, sendAmount);\n    }\n\n    function approve(address _spender, uint256 amount) external {\n        allowance[msg.sender][_spender] = amount;\n        emit Approval(msg.sender, _spender, amount);\n    }\n\n    // For testing, just don't limit access on setting fees\n    function setParams(uint256 newBasisPoints, uint256 newMaxFee) public {\n        basisPointsRate = newBasisPoints;\n        maximumFee = newMaxFee * (10**decimals);\n\n        emit Params(basisPointsRate, maximumFee);\n    }\n}\n\n/**\n * @title The Compound Faucet Test Token\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract NonStandardFaucetFeeToken is NonStandardFeeToken {\n    constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol)\n        NonStandardFeeToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n    }\n\n    function allocateTo(address _owner, uint256 value) public {\n        balanceOf[_owner] += value;\n        totalSupply += value;\n        emit Transfer(address(this), _owner, value);\n    }\n}\n"},{"file_path":"contracts/test/SimpleTimelock.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @dev Simple Timelock for more realistic deployments and scenarios.\n *  Note: do not use in production!\n */\ncontract SimpleTimelock {\n    event NewAdmin(address indexed newAdmin);\n    event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\n    event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\n    event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\n\n    address public admin;\n    mapping (bytes32 => bool) public queuedTransactions;\n\n    // For GovernorBravo initiation and compatability\n    uint public constant proposalCount = 1;\n    uint public constant delay = 0;\n    uint public constant GRACE_PERIOD = 14 days;\n\n    error Unauthorized();\n\n    constructor(address admin_) {\n        admin = admin_;\n    }\n\n    receive() external payable {}\n\n    function acceptAdmin() external {\n        return; // Note: not used, just for GovernorBravo compatability\n    }\n\n    function setAdmin(address newAdmin) external {\n        if (msg.sender != admin) revert Unauthorized();\n        admin = newAdmin;\n\n        emit NewAdmin(newAdmin);\n    }\n\n    function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external returns (bytes32) {\n        if (msg.sender != admin) revert Unauthorized();\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        queuedTransactions[txHash] = true;\n\n        emit QueueTransaction(txHash, target, value, signature, data, eta);\n        return txHash;\n    }\n\n    function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external {\n        if (msg.sender != admin) revert Unauthorized();\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        queuedTransactions[txHash] = false;\n\n        emit CancelTransaction(txHash, target, value, signature, data, eta);\n    }\n\n    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) external payable returns (bytes memory) {\n        if (msg.sender != admin) revert Unauthorized();\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        require(queuedTransactions[txHash], \"Timelock::executeTransaction: Transaction hasn't been queued.\");\n\n        queuedTransactions[txHash] = false;\n\n        bytes memory callData;\n\n        if (bytes(signature).length == 0) {\n            callData = data;\n        } else {\n            callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);\n        }\n\n        (bool success, bytes memory returnData) = target.call{value: value}(callData);\n        require(success, \"Timelock::executeTransaction: Transaction execution reverted.\");\n\n        emit ExecuteTransaction(txHash, target, value, signature, data, eta);\n\n        return returnData;\n    }\n\n    // Executes multiple transactions without having to queue them up. Used for easier testing. Can be removed.\n    function executeTransactions(address[] calldata targets, uint[] calldata values, string[] calldata signatures, bytes[] calldata data) external payable {\n        if (msg.sender != admin) revert Unauthorized();\n\n        for (uint i = 0; i < targets.length; i++) {\n            bytes memory callData;\n\n            if (bytes(signatures[i]).length == 0) {\n                callData = data[i];\n            } else {\n                callData = abi.encodePacked(bytes4(keccak256(bytes(signatures[i]))), data[i]);\n            }\n\n            (bool success, ) = targets[i].call{value: values[i]}(callData);\n            require(success, \"failed to call\");\n        }\n    }\n}\n"},{"file_path":"contracts/IRateProvider.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\ninterface IRateProvider {\n    function getRate() external view returns (uint256);\n}\n"},{"file_path":"contracts/live-test/PriceFeedLiveTest.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\n/**\n * @title PriceFeedLiveTest\n * @notice A TEST-ONLY price feed for live, on-chain testing. It either passes\n *         prices straight through from a real source feed, or serves a\n *         hand-set constant price — toggled at runtime by an authorized admin.\n * @dev NOT for production use. Because the constant price is arbitrary and set\n *      by a role holder, any market wired to this feed can be manipulated at\n *      will; never point a production Comet at it.\n *\n *      Implements the full Chainlink {AggregatorV3Interface} (both\n *      `getRoundData` and `latestRoundData`). In constant mode `startedAt` /\n *      `updatedAt` are always reported as `block.timestamp`, so the feed never\n *      appears stale to any staleness check.\n * @author Woof\n */\ncontract PriceFeedLiveTest is AggregatorV3Interface, AccessControl {\n    uint256 public constant override version = 1;\n    uint8 public immutable override decimals;\n    AggregatorV3Interface public immutable sourcePriceFeed;\n\n    /// @notice When true, prices are fetched from {sourcePriceFeed}; when false,\n    ///         the hand-set {constantPrice} is served instead\n    bool public useSourceFeed;\n    /// @notice The constant price served while source mode is off\n    int256 public constantPrice;\n    /// @notice Monotonic round id for the constant-price mode, bumped on every {setPrice}\n    uint80 internal constantRoundId;\n    /// @notice Description and testing purpose of price feed\n    string public description;\n\n    /// @notice Thrown when passed values is equal to already stored one\n    error SameValue();\n    /// @notice Emitted when the constant price is updated\n    event PriceSet(int256 price);\n    /// @notice Emitted when the price source mode is toggled\n    event SourceFeedModeSet(bool useSourceFeed);\n\n    constructor(address sourcePriceFeed_, uint8 decimals_, address admin_, string memory description_) {\n        sourcePriceFeed = AggregatorV3Interface(sourcePriceFeed_);\n        decimals = decimals_;\n        useSourceFeed = true;\n        description = description_;\n\n        _grantRole(DEFAULT_ADMIN_ROLE, admin_);\n    }\n\n    /**\n     * @notice Set the constant price served while source mode is off\n     * @param price_ The new constant price, in this feed's {decimals}\n     **/\n    function setPrice(int256 price_) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (price_ == constantPrice) revert SameValue();\n        constantPrice = price_;\n        unchecked { constantRoundId++; }\n        emit PriceSet(price_);\n    }\n\n    /**\n     * @notice Toggle between the source feed and the constant price\n     * @param useSourceFeed_ True to pass through {sourcePriceFeed}, false to serve {constantPrice}\n     **/\n    function setUseSourceFeed(bool useSourceFeed_) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (useSourceFeed_ == useSourceFeed) revert SameValue();\n        useSourceFeed = useSourceFeed_;\n        emit SourceFeedModeSet(useSourceFeed_);\n    }\n\n    /**\n     * @notice Price data for a specific round\n     * @dev In source mode this is proxied to the underlying feed. In constant\n     *      mode the requested round is echoed back with the current constant\n     *      price and a fresh (non-stale) timestamp.\n     **/\n    function getRoundData(uint80 roundId_) external view override returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        if (useSourceFeed) {\n            return sourcePriceFeed.getRoundData(roundId_);\n        }\n        return (roundId_, constantPrice, block.timestamp, block.timestamp, roundId_);\n    }\n\n    /**\n     * @notice Price data for the latest round\n     * @dev In source mode this is proxied to the underlying feed. In constant\n     *      mode the current constant price is returned with a fresh (non-stale)\n     *      timestamp, so it satisfies any staleness check.\n     **/\n    function latestRoundData() external view override returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        if (useSourceFeed) {\n            return sourcePriceFeed.latestRoundData();\n        }\n        return (constantRoundId, constantPrice, block.timestamp, block.timestamp, constantRoundId);\n    }\n}"},{"file_path":"contracts/pricefeeds/ScalingPriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title Scaling price feed\n * @notice A custom price feed that scales up or down the price received from an underlying price feed and returns the result\n * @author Compound\n */\ncontract ScalingPriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error InvalidInt256();\n\n    /// @notice Version of the price feed\n    uint public constant override version = 1;\n\n    /// @notice Description of the price feed\n    string public description;\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Underlying price feed where prices are fetched from\n    address public immutable underlyingPriceFeed;\n\n    /// @notice Whether or not the price should be upscaled\n    bool internal immutable shouldUpscale;\n\n    /// @notice The amount to upscale or downscale the price by\n    int256 internal immutable rescaleFactor;\n\n    /**\n     * @notice Construct a new scaling price feed\n     * @param underlyingPriceFeed_ The address of the underlying price feed to fetch prices from\n     * @param decimals_ The number of decimals for the returned prices\n     **/\n    constructor(address underlyingPriceFeed_, uint8 decimals_) {\n        underlyingPriceFeed = underlyingPriceFeed_;\n        decimals = decimals_;\n        description = AggregatorV3Interface(underlyingPriceFeed_).description();\n\n        uint8 underlyingPriceFeedDecimals = AggregatorV3Interface(underlyingPriceFeed_).decimals();\n        // Note: Solidity does not allow setting immutables in if/else statements\n        shouldUpscale = underlyingPriceFeedDecimals < decimals_ ? true : false;\n        rescaleFactor = (shouldUpscale\n            ? signed256(10 ** (decimals_ - underlyingPriceFeedDecimals))\n            : signed256(10 ** (underlyingPriceFeedDecimals - decimals_))\n        );\n    }\n\n    /**\n     * @notice Price for the latest round\n     * @return roundId Round id from the underlying price feed\n     * @return answer Latest price for the asset in terms of ETH\n     * @return startedAt Timestamp when the round was started; passed on from underlying price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from underlying price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed\n     **/\n    function latestRoundData() override external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        (uint80 roundId_, int256 price, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(underlyingPriceFeed).latestRoundData();\n        return (roundId_, scalePrice(price), startedAt_, updatedAt_, answeredInRound_);\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 scalePrice(int256 price) internal view returns (int256) {\n        int256 scaledPrice;\n        if (shouldUpscale) {\n            scaledPrice = price * rescaleFactor;\n        } else {\n            scaledPrice = price / rescaleFactor;\n        }\n        return scaledPrice;\n    }\n}"},{"file_path":"contracts/bridges/scroll/IScrollMessenger.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/// @notice IScrollMessenger is the interface for Scroll's messenger contract\ninterface IScrollMessenger {\n  function xDomainMessageSender() external view returns (address);\n}\n"},{"file_path":"contracts/AssetListFactory.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./AssetList.sol\";\n\n/**\n * @title Compound's Asset List Factory\n * @author Compound\n */\ncontract AssetListFactory {\n    event AssetListCreated(address indexed assetList, CometCore.AssetConfig[] assetConfigs);\n\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        assetList = address(new AssetList(assetConfigs));\n        emit AssetListCreated(assetList, assetConfigs);\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolEvents.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Events emitted by a pool\n/// @notice Contains all events emitted by the pool\ninterface IUniswapV3PoolEvents {\n    /// @notice Emitted exactly once by a pool when #initialize is first called on the pool\n    /// @dev Mint/Burn/Swap cannot be emitted by the pool before Initialize\n    /// @param sqrtPriceX96 The initial sqrt price of the pool, as a Q64.96\n    /// @param tick The initial tick of the pool, i.e. log base 1.0001 of the starting price of the pool\n    event Initialize(uint160 sqrtPriceX96, int24 tick);\n\n    /// @notice Emitted when liquidity is minted for a given position\n    /// @param sender The address that minted the liquidity\n    /// @param owner The owner of the position and recipient of any minted liquidity\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount The amount of liquidity minted to the position range\n    /// @param amount0 How much token0 was required for the minted liquidity\n    /// @param amount1 How much token1 was required for the minted liquidity\n    event Mint(\n        address sender,\n        address indexed owner,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount,\n        uint256 amount0,\n        uint256 amount1\n    );\n\n    /// @notice Emitted when fees are collected by the owner of a position\n    /// @dev Collect events may be emitted with zero amount0 and amount1 when the caller chooses not to collect fees\n    /// @param owner The owner of the position for which fees are collected\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount0 The amount of token0 fees collected\n    /// @param amount1 The amount of token1 fees collected\n    event Collect(\n        address indexed owner,\n        address recipient,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount0,\n        uint128 amount1\n    );\n\n    /// @notice Emitted when a position's liquidity is removed\n    /// @dev Does not withdraw any fees earned by the liquidity position, which must be withdrawn via #collect\n    /// @param owner The owner of the position for which liquidity is removed\n    /// @param tickLower The lower tick of the position\n    /// @param tickUpper The upper tick of the position\n    /// @param amount The amount of liquidity to remove\n    /// @param amount0 The amount of token0 withdrawn\n    /// @param amount1 The amount of token1 withdrawn\n    event Burn(\n        address indexed owner,\n        int24 indexed tickLower,\n        int24 indexed tickUpper,\n        uint128 amount,\n        uint256 amount0,\n        uint256 amount1\n    );\n\n    /// @notice Emitted by the pool for any swaps between token0 and token1\n    /// @param sender The address that initiated the swap call, and that received the callback\n    /// @param recipient The address that received the output of the swap\n    /// @param amount0 The delta of the token0 balance of the pool\n    /// @param amount1 The delta of the token1 balance of the pool\n    /// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96\n    /// @param liquidity The liquidity of the pool after the swap\n    /// @param tick The log base 1.0001 of price of the pool after the swap\n    event Swap(\n        address indexed sender,\n        address indexed recipient,\n        int256 amount0,\n        int256 amount1,\n        uint160 sqrtPriceX96,\n        uint128 liquidity,\n        int24 tick\n    );\n\n    /// @notice Emitted by the pool for any flashes of token0/token1\n    /// @param sender The address that initiated the swap call, and that received the callback\n    /// @param recipient The address that received the tokens from flash\n    /// @param amount0 The amount of token0 that was flashed\n    /// @param amount1 The amount of token1 that was flashed\n    /// @param paid0 The amount of token0 paid for the flash, which can exceed the amount0 plus the fee\n    /// @param paid1 The amount of token1 paid for the flash, which can exceed the amount1 plus the fee\n    event Flash(\n        address indexed sender,\n        address indexed recipient,\n        uint256 amount0,\n        uint256 amount1,\n        uint256 paid0,\n        uint256 paid1\n    );\n\n    /// @notice Emitted by the pool for increases to the number of observations that can be stored\n    /// @dev observationCardinalityNext is not the observation cardinality until an observation is written at the index\n    /// just before a mint/swap/burn.\n    /// @param observationCardinalityNextOld The previous value of the next observation cardinality\n    /// @param observationCardinalityNextNew The updated value of the next observation cardinality\n    event IncreaseObservationCardinalityNext(\n        uint16 observationCardinalityNextOld,\n        uint16 observationCardinalityNextNew\n    );\n\n    /// @notice Emitted when the protocol fee is changed by the pool\n    /// @param feeProtocol0Old The previous value of the token0 protocol fee\n    /// @param feeProtocol1Old The previous value of the token1 protocol fee\n    /// @param feeProtocol0New The updated value of the token0 protocol fee\n    /// @param feeProtocol1New The updated value of the token1 protocol fee\n    event SetFeeProtocol(uint8 feeProtocol0Old, uint8 feeProtocol1Old, uint8 feeProtocol0New, uint8 feeProtocol1New);\n\n    /// @notice Emitted when the collected protocol fees are withdrawn by the factory owner\n    /// @param sender The address that collects the protocol fees\n    /// @param recipient The address that receives the collected protocol fees\n    /// @param amount0 The amount of token0 protocol fees that is withdrawn\n    /// @param amount0 The amount of token1 protocol fees that is withdrawn\n    event CollectProtocol(address indexed sender, address indexed recipient, uint128 amount0, uint128 amount1);\n}\n"},{"file_path":"contracts/test/CometModified.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../CometWithExtendedAssetList.sol\";\n\n/**\n * @title A modified version of Compound Comet\n * @notice This is solely used for testing upgrades\n * @author Compound\n */\ncontract CometModified is CometWithExtendedAssetList {\n\n    constructor(Configuration memory config) CometWithExtendedAssetList(config) {}\n\n    /**\n     * @notice Initialize storage for a liquidator\n     * @dev Solely used for testing upgrades\n     */\n    function initialize(address liquidator) external {\n        liquidatorPoints[liquidator].numAbsorbs = type(uint32).max;\n    }\n\n    function newFunction() external pure returns (int) {\n        return 101;\n    }\n}\n"},{"file_path":"contracts/pricefeeds/WstETHPriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../IPriceFeed.sol\";\nimport \"../IWstETH.sol\";\n\n/**\n * @title wstETH price feed\n * @notice A custom price feed that calculates the price for wstETH / ETH\n * @author Compound\n */\ncontract WstETHPriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error BadDecimals();\n    error InvalidInt256();\n\n    /// @notice Version of the price feed\n    uint public constant override version = 1;\n\n    /// @notice Description of the price feed\n    string public constant override description = \"Custom price feed for wstETH / ETH\";\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Chainlink stETH / ETH price feed\n    address public immutable stETHtoETHPriceFeed;\n\n    /// @notice Number of decimals for the stETH / ETH price feed\n    uint public immutable stETHToETHPriceFeedDecimals;\n\n    /// @notice WstETH contract address\n    address public immutable wstETH;\n\n    /// @notice Scale for WstETH contract\n    int public immutable wstETHScale;\n\n    constructor(address stETHtoETHPriceFeed_, address wstETH_, uint8 decimals_) {\n        stETHtoETHPriceFeed = stETHtoETHPriceFeed_;\n        stETHToETHPriceFeedDecimals = AggregatorV3Interface(stETHtoETHPriceFeed_).decimals();\n        wstETH = wstETH_;\n        // Note: Safe to convert directly to an int256 because wstETH.decimals == 18\n        wstETHScale = int256(10 ** IWstETH(wstETH).decimals());\n\n        // Note: stETH / ETH price feed has 18 decimals so `decimals_` should always be less than or equals to that\n        if (decimals_ > stETHToETHPriceFeedDecimals) revert BadDecimals();\n        decimals = decimals_;\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    /**\n     * @notice WstETH price for the latest round\n     * @return roundId Round id from the stETH price feed\n     * @return answer Latest price for wstETH / USD\n     * @return startedAt Timestamp when the round was started; passed on from stETH price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from stETH price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from stETH price feed\n     **/\n    function latestRoundData() override external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        (uint80 roundId_, int256 stETHPrice, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(stETHtoETHPriceFeed).latestRoundData();\n        uint256 tokensPerStEth = IWstETH(wstETH).tokensPerStEth();\n        int256 price = stETHPrice * wstETHScale / signed256(tokensPerStEth);\n        // Note: The stETH price feed should always have an equal or larger amount of decimals than this price feed (enforced by validation in constructor)\n        int256 scaledPrice = price / int256(10 ** (stETHToETHPriceFeedDecimals - decimals));\n        return (roundId_, scaledPrice, startedAt_, updatedAt_, answeredInRound_);\n    }\n}"},{"file_path":"contracts/test/Fauceteer.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../ERC20.sol\";\n\ncontract Fauceteer {\n    /// @notice Mapping of user address -> asset address -> last time the user\n    /// received that asset\n    mapping(address => mapping(address => uint)) public lastReceived;\n\n    /* errors */\n    error BalanceTooLow();\n    error RequestedTooFrequently();\n    error TransferFailed();\n\n    function drip(address token) public {\n        uint balance = ERC20(token).balanceOf(address(this));\n        if (balance <= 0) revert BalanceTooLow();\n\n        if (block.timestamp - lastReceived[msg.sender][token] < 1 days) revert RequestedTooFrequently();\n\n        lastReceived[msg.sender][token] = block.timestamp;\n\n        bool success = ERC20(token).transfer(msg.sender, balance / 10000); // 0.01%\n        if (!success) revert TransferFailed();\n    }\n}"},{"file_path":"@openzeppelin/contracts/access/IAccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\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/marketupdates/MarketUpdateProposer.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./../ITimelock.sol\";\n\n/**\n* @title MarketUpdateProposer\n* @notice This contract allows for the creation of proposals that can be executed by the timelock\n* @dev This contract is used to propose market updates\n* Few important points to note:\n* 1) The marketAdmin can propose updates. The marketAdmin can be set by the governor. marketAdmin will be a multi-sig.\n* 2) Here governor is the main-governor-timelock. This terminology(using governor as variable for timelock) is for\n*    consistency with Configurator.sol.\n* 3) If marketAdmin/multi-sig is compromised, the new marketAdmin can be set by the governor.\n* 4) While the marketAdmin/multi-sig is compromised, the new marketAdmin can propose updates. But those updates will be\n*    sent to timelock and can be paused by the marketAdminPauseGuardian Configurator and CometProxyAdmin.\n* 5) The proposalGuardian can also be used for the same purpose and can cancel the proposal.\n*\n*\n*/\ncontract MarketUpdateProposer {\n    struct MarketUpdateProposal {\n        /// @notice Unique id for looking up a proposal\n        uint id;\n\n        /// @notice Creator of the proposal\n        address proposer;\n\n        /// @notice The timestamp that the proposal will be available for execution, set once the vote succeeds\n        uint eta;\n\n        /// @notice the ordered list of target addresses for calls to be made\n        address[] targets;\n\n        /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made\n        uint[] values;\n\n        /// @notice The ordered list of function signatures to be called\n        string[] signatures;\n\n        /// @notice The ordered list of calldata to be passed to each call\n        bytes[] calldatas;\n\n        /// @notice Flag marking whether the proposal has been canceled\n        bool canceled;\n\n        /// @notice Flag marking whether the proposal has been executed\n        bool executed;\n    }\n\n    enum ProposalState {\n        Canceled,\n        Queued,\n        Executed,\n        Expired\n    }\n\n    address public governor;\n    address public proposalGuardian;\n    address public marketAdmin;\n    ITimelock public timelock;\n\n    /// @notice The official record of all proposals ever proposed\n    mapping(uint => MarketUpdateProposal) public proposals;\n    /// @notice The total number of proposals\n    uint public proposalCount;\n\n    /// @notice The initial proposal ID, set when the contract is deployed\n    uint public constant INITIAL_PROPOSAL_ID = 0;\n    \n    /// @notice The maximum number of actions that can be included in a proposal\n    uint public constant PROPOSAL_MAX_OPERATIONS = 20; // 20 actions\n\n    /// @notice An event emitted when a new proposal is created\n    event MarketUpdateProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, string description);\n    event MarketUpdateProposalExecuted(uint id);\n    event MarketUpdateProposalCancelled(uint id);\n    event SetProposalGuardian(address indexed oldProposalGuardian, address indexed newProposalGuardian);\n    event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin);\n    event SetGovernor(address indexed oldGovernor, address indexed newGovernor);\n\n    error Unauthorized();\n    error InvalidAddress();\n\n    constructor(address governor_, address marketAdmin_, address proposalGuardian_, ITimelock timelock_) public {\n        if (governor_ == address(0) || marketAdmin_ == address(0) || address(timelock_) == address(0)) revert InvalidAddress();\n        governor = governor_;\n        marketAdmin = marketAdmin_;\n        proposalGuardian = proposalGuardian_;\n        timelock = timelock_;\n    }\n    \n    /**\n     * @notice Transfers the governor rights to a new address\n     * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the governor.\n     * Emits an event with the old and new governor addresses.\n     * @param newGovernor The address of the new governor.\n     */\n    function setGovernor(address newGovernor) external {\n        if (msg.sender != governor) revert Unauthorized();\n        if (address(newGovernor) == address(0)) revert InvalidAddress();\n        \n        address oldGovernor = governor;\n        governor = newGovernor;\n        emit SetGovernor(oldGovernor, newGovernor);\n    }\n    \n    /**\n     * @notice Sets a new proposalGuardian.\n     * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the owner.\n     * Emits an event with the old and new proposalGuardian addresses.\n     * Note that there is no enforced zero address check on `newProposalGuardian` as it may be a deliberate choice\n     * to assign the zero address in certain scenarios. This design allows flexibility if the zero address\n     * is intended to represent a specific state, such as temporarily disabling the proposalGuardian.\n     * @param newProposalGuardian The address of the new market admin proposalGuardian.\n     */\n    function setProposalGuardian(address newProposalGuardian) external {\n        if (msg.sender != governor) revert Unauthorized();\n        address oldProposalGuardian = proposalGuardian;\n        proposalGuardian = newProposalGuardian;\n        emit SetProposalGuardian(oldProposalGuardian, newProposalGuardian);\n    }\n\n    /**\n     * @notice Sets a new market admin.\n     * @dev Can only be called by the governor. Reverts with Unauthorized if the caller is not the governor.\n     * Emits an event with the old and new market admin addresses.\n     * Note that there is no enforced zero address check on `newMarketAdmin` as it may be a deliberate choice\n     * to assign the zero address in certain scenarios. This design allows flexibility if the zero address\n     * is intended to represent a specific state, such as temporarily disabling the market admin role.\n     * @param newMarketAdmin The address of the new market admin.\n     */\n    function setMarketAdmin(address newMarketAdmin) external {\n        if (msg.sender != governor) revert Unauthorized();\n        address oldMarketAdmin = marketAdmin;\n        marketAdmin = newMarketAdmin;\n        emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin);\n    }\n    \n    /**\n     * @notice Function used to propose a new proposal for market updates\n     * @dev Can only be called by the market admin. Reverts with Unauthorized if the caller is not the market admin\n     * The function requires the provided arrays to have the same length and at least one action\n     * Emits a MarketUpdateProposalCreated event with the proposal details\n     * @param targets Target addresses for proposal calls\n     * @param values Eth values for proposal calls\n     * @param signatures Function signatures for proposal calls\n     * @param calldatas Calldatas for proposal calls\n     * @param description String description of the proposal\n     * @return Proposal id of new proposal\n     */\n    function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public returns (uint) {\n        if (msg.sender != marketAdmin) revert Unauthorized();\n        require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, \"MarketUpdateProposer::propose: proposal function information arity mismatch\");\n        require(targets.length != 0, \"MarketUpdateProposer::propose: must provide actions\");\n        require(targets.length <= PROPOSAL_MAX_OPERATIONS, \"MarketUpdateProposer::propose: too many actions\");\n        \n        proposalCount++;\n        uint newProposalID = proposalCount;\n        MarketUpdateProposal storage newProposal = proposals[newProposalID];\n\n        require(newProposal.id == 0, \"MarketUpdateProposer::propose: ProposalID collision\");\n        uint eta = block.timestamp + timelock.delay();\n        newProposal.id = newProposalID;\n        newProposal.proposer = msg.sender;\n        newProposal.eta = eta;\n        newProposal.targets = targets;\n        newProposal.values = values;\n        newProposal.signatures = signatures;\n        newProposal.calldatas = calldatas;\n        newProposal.canceled = false;\n        newProposal.executed = false;\n\n        emit MarketUpdateProposalCreated(newProposal.id, msg.sender, targets, values, signatures, calldatas, description);\n\n        for (uint i = 0; i < newProposal.targets.length; i++) {\n            queueOrRevertInternal(newProposal.targets[i], newProposal.values[i], newProposal.signatures[i], newProposal.calldatas[i], eta);\n        }\n\n        return newProposal.id;\n    }\n\n    function queueOrRevertInternal(address target, uint value, string memory signature, bytes memory data, uint eta) internal {\n        require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data, eta))), \"MarketUpdateProposer::queueOrRevertInternal: identical proposal action already queued at eta\");\n        timelock.queueTransaction(target, value, signature, data, eta);\n    }\n\n    /**\n      * @notice Executes a queued proposal if eta has passed\n      * @param proposalId The id of the proposal to execute\n      */\n    function execute(uint proposalId) external payable {\n        if (msg.sender != marketAdmin) revert Unauthorized();\n        require(state(proposalId) == ProposalState.Queued, \"MarketUpdateProposer::execute: proposal can only be executed if it is queued\");\n        MarketUpdateProposal storage proposal = proposals[proposalId];\n        proposal.executed = true;\n        for (uint i = 0; i < proposal.targets.length; i++) {\n            timelock.executeTransaction{value: proposal.values[i]}(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta);\n        }\n        emit MarketUpdateProposalExecuted(proposalId);\n    }\n\n    /**\n      * @notice Cancels a proposal only if sender is the proposer, proposalGuardian, or marketAdmin, and the proposal is not already executed\n      * @param proposalId The id of the proposal to cancel\n      */\n    function cancel(uint proposalId) external {\n        if (msg.sender != governor && msg.sender != proposalGuardian && msg.sender != marketAdmin) revert Unauthorized();\n        require(state(proposalId) != ProposalState.Executed, \"MarketUpdateProposer::cancel: cannot cancel executed proposal\");\n\n        MarketUpdateProposal storage proposal = proposals[proposalId];\n\n        proposal.canceled = true;\n        for (uint i = 0; i < proposal.targets.length; i++) {\n            timelock.cancelTransaction(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta);\n        }\n\n        emit MarketUpdateProposalCancelled(proposalId);\n    }\n\n    /**\n     * @notice Gets the state of a proposal\n     * @param proposalId The id of the proposal\n     * @return Proposal state\n     */\n    function state(uint proposalId) public view returns (ProposalState) {\n        require(proposalCount >= proposalId && proposalId > INITIAL_PROPOSAL_ID, \"MarketUpdateProposer::state: invalid proposal id\");\n        MarketUpdateProposal storage proposal = proposals[proposalId];\n        if (proposal.canceled) {\n            return ProposalState.Canceled;\n        } else if (proposal.executed) {\n            return ProposalState.Executed;\n        } else if (block.timestamp >= (proposal.eta + timelock.GRACE_PERIOD())) {\n            return ProposalState.Expired;\n        } else {\n            return ProposalState.Queued;\n        }\n    }\n\n\n    /**\n     * @notice Get details of a proposal by its id\n     * @param proposalId The id of the proposal\n     * @return id The id of the proposal\n     * @return proposer The address of the proposer\n     * @return eta The estimated time at which the proposal can be executed\n     * @return targets targets of the proposal actions\n     * @return values ETH values of the proposal actions\n     * @return signatures signatures of the proposal actions\n     * @return calldatas calldatas of the proposal actions\n     * @return canceled boolean indicating whether the proposal has been canceled\n     * @return executed boolean indicating whether the proposal has been executed\n     */\n    function getProposal(uint proposalId) public view\n        returns (\n            uint,\n            address,\n            uint,\n            address[] memory,\n            uint[] memory,\n            string[] memory,\n            bytes[] memory,\n            bool,\n            bool\n        )\n    {\n        MarketUpdateProposal storage proposal = proposals[proposalId];\n        return (\n            proposal.id,\n            proposal.proposer,\n            proposal.eta,\n            proposal.targets,\n            proposal.values,\n            proposal.signatures,\n            proposal.calldatas,\n            proposal.canceled,\n            proposal.executed\n        );\n    }\n}\n"},{"file_path":"contracts/bridges/polygon/IFxMessageProcessor.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n// IFxMessageProcessor represents interface to process message\ninterface IFxMessageProcessor {\n    function processMessageFromRoot(\n        uint256 stateId,\n        address rootMessageSender,\n        bytes calldata data\n    ) external;\n}"},{"file_path":"contracts/bridges/scroll/ScrollBridgeReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../SweepableBridgeReceiver.sol\";\nimport \"./IScrollMessenger.sol\";\n\n/// @title Scroll Bridge Receiver\n/// @notice Contract that processes messages passed from Compound governance using the Scroll bridge\ncontract ScrollBridgeReceiver is SweepableBridgeReceiver {\n    error InvalidL2Messenger();\n\n    event NewL2Messenger(address indexed oldL2Messenger, address indexed newL2Messenger);\n\n    /// @notice Address of Scroll L2 Messenger contract\n    address public l2Messenger;\n\n    /// @notice Construct a new ScrollBridgeReceiver instance\n    /// @param l2Messenger_ Address of Scroll L2 Messenger contract\n    constructor(address l2Messenger_) {\n        l2Messenger = l2Messenger_;\n        emit NewL2Messenger(address(0), l2Messenger_);\n    }\n\n    /// @notice Update the L2 Messenger address\n    /// @param newL2Messenger New address for L2 Messenger contract\n    function changeL2Messenger(address newL2Messenger) public {\n        if (msg.sender != localTimelock) revert Unauthorized();\n        address oldL2Messenger = l2Messenger;\n        l2Messenger = newL2Messenger;\n        emit NewL2Messenger(oldL2Messenger, newL2Messenger);\n    }\n\n    /// @notice Fallback function to handle messages\n    fallback() external payable {\n        if (msg.sender != l2Messenger) revert InvalidL2Messenger();\n        address messageSender = IScrollMessenger(msg.sender).xDomainMessageSender();\n        processMessage(messageSender, msg.data);\n    }\n}"},{"file_path":"contracts/ConfiguratorStorage.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometConfiguration.sol\";\nimport \"./marketupdates/MarketAdminPermissionCheckerInterface.sol\";\n\n/**\n * @title Compound's Comet Configuration Storage Interface\n * @dev Versions can enforce append-only storage slots via inheritance.\n * @author Compound\n */\ncontract ConfiguratorStorage is CometConfiguration {\n    /// @notice The current version of Configurator. This version should be\n    /// checked in the initializer function.\n    uint public version;\n\n    /// @notice Mapping of Comet proxy addresses to their Configuration settings\n    /// @dev This needs to be internal to avoid a `CompilerError: Stack too deep\n    /// when compiling inline assembly` error that is caused by the default\n    /// getters created for public variables.\n    mapping(address => Configuration) internal configuratorParams;\n\n    /// @notice The governor of the protocol\n    address public governor;\n\n    /// @notice Mapping of Comet proxy addresses to their Comet factory contracts\n    mapping(address => address) public factory;\n\n    /// @notice MarketAdminPermissionChecker contract which is used to check if the caller has permission to perform market updates\n    MarketAdminPermissionCheckerInterface public marketAdminPermissionChecker;\n}\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/marketupdates/MarketAdminPermissionChecker.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./../vendor/access/Ownable.sol\";\nimport \"./MarketAdminPermissionCheckerInterface.sol\";\n\ncontract MarketAdminPermissionChecker is MarketAdminPermissionCheckerInterface, Ownable {\n    /// @notice The address of the market admin. This will be the address of the market update timelock contract.\n    address public marketAdmin;\n    \n    /// @notice Pause flag for the market admin\n    bool public marketAdminPaused;\n\n    /// @notice address of the market admin pause guardian.\n    address public marketAdminPauseGuardian;\n\n    event SetMarketAdmin(address indexed oldAdmin, address indexed newAdmin);\n    event SetMarketAdminPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian);\n    event MarketAdminPaused(address indexed caller, bool isMarketAdminPaused);\n\n    /**\n     * @notice Construct a new MarketAdminPermissionChecker contract.\n     * Not adding any checks for zero address as it may be a deliberate choice to assign the zero address i.e. keep the\n     * market updates disabled.\n     * @param initialOwner The address of the owner.\n     * @param marketAdmin_ The address of the market admin.\n     * @param marketAdminPauseGuardian_ The address of the market admin pause guardian.\n     */\n    constructor(address initialOwner, address marketAdmin_, address marketAdminPauseGuardian_) Ownable(initialOwner) {\n        marketAdmin = marketAdmin_;\n        marketAdminPauseGuardian = marketAdminPauseGuardian_;\n    }\n    /**\n     * @notice Sets a new market admin.\n     * @dev Can only be called by the main-governor-timelock. Reverts with Unauthorized if the caller is not the main-governor-timelock.\n     * Emits an event with the old and new market admin addresses.\n     * Note that there is no enforced zero address check on `newMarketAdmin` as it may be a deliberate choice\n     * to assign the zero address in certain scenarios. This design allows flexibility if the zero address\n     * is intended to represent a specific state, such as temporarily disabling the market admin role.\n     * @param newMarketAdmin The address of the new market admin.\n     */\n    function setMarketAdmin(address newMarketAdmin) external onlyOwner {\n        address oldMarketAdmin = marketAdmin;\n        marketAdmin = newMarketAdmin;\n        emit SetMarketAdmin(oldMarketAdmin, newMarketAdmin);\n    }\n\n    /**\n     * @notice Sets a new market admin pause guardian.\n     * @dev Can only be called by the main-governor-timelock. Reverts with Unauthorized if the caller is not the owner.\n     * @param newPauseGuardian The address of the new market admin pause guardian.\n     * Note that there is no enforced zero address check on `newPauseGuardian` as it may be a deliberate choice\n     * to assign the zero address in certain scenarios. This design allows flexibility if the zero address\n     * is intended to represent a specific state, such as temporarily disabling the pause guardian.\n     */\n    function setMarketAdminPauseGuardian(address newPauseGuardian) external onlyOwner {\n        address oldPauseGuardian = marketAdminPauseGuardian;\n        marketAdminPauseGuardian = newPauseGuardian;\n        emit SetMarketAdminPauseGuardian(oldPauseGuardian, newPauseGuardian);\n    }\n\n    /**\n     * @notice Pauses the market admin role.\n     * @dev Can only be called by the main-governor-timelock or the market admin pause guardian.\n     * Reverts with Unauthorized if the caller is neither.\n     */\n    function pauseMarketAdmin() external {\n        if (msg.sender != owner() && msg.sender != marketAdminPauseGuardian) revert Unauthorized();\n        marketAdminPaused = true;\n        emit MarketAdminPaused(msg.sender, true);\n    }\n\n    /**\n     * @notice Unpauses the market admin role.\n     * @dev Can only be called by the main-governor-timelock.\n     * Reverts with Unauthorized if the caller is not the main-governor-timelock.\n     */\n    function unpauseMarketAdmin() external onlyOwner {\n        marketAdminPaused = false;\n        emit MarketAdminPaused(msg.sender, false);\n    }\n\n    /**\n     * @notice Checks if the caller can perform market updates or not.\n     * Throws an error if the callerAddress is not same as market admin, or if the market admin is paused\n     * @param callerAddress The address of the caller\n     */\n    function checkUpdatePermission(address callerAddress) external view {\n        if (callerAddress != marketAdmin) revert Unauthorized();\n        if (marketAdminPaused) revert MarketAdminIsPaused();\n    }\n}\n"},{"file_path":"contracts/ERC20.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title ERC 20 Token Standard Interface\n *  https://eips.ethereum.org/EIPS/eip-20\n */\ninterface ERC20 {\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 Get the total number of tokens in circulation\n      * @return The supply of tokens\n      */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @notice Gets the balance of the specified address\n     * @param owner The address from which the balance will be retrieved\n     * @return The balance\n     */\n    function balanceOf(address owner) external view returns (uint256);\n\n    /**\n      * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n      * @param dst The address of the destination account\n      * @param amount The number of tokens to transfer\n      * @return Whether or not the transfer succeeded\n      */\n    function transfer(address dst, uint256 amount) external returns (bool);\n\n    /**\n      * @notice Transfer `amount` tokens from `src` to `dst`\n      * @param src The address of the source account\n      * @param dst The address of the destination account\n      * @param amount The number of tokens to transfer\n      * @return Whether or not the transfer succeeded\n      */\n    function transferFrom(address src, address dst, uint256 amount) external returns (bool);\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      * @return Whether or not the approval succeeded\n      */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n      * @notice Get the current allowance from `owner` for `spender`\n      * @param owner The address of the account which owns the tokens to be spent\n      * @param spender The address of the account which may transfer tokens\n      * @return The number of tokens allowed to be spent (-1 means infinite)\n      */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n}\n"},{"file_path":"contracts/liquidator/interfaces/IVault.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @dev Interfaces for interacting with Balancer Vaults\n * Note Not comprehensive\n */\ninterface IVault {\n    enum SwapKind { GIVEN_IN, GIVEN_OUT }\n\n    struct BatchSwapStep {\n        bytes32 poolId;\n        uint256 assetInIndex;\n        uint256 assetOutIndex;\n        uint256 amount;\n        bytes userData;\n    }\n\n    struct FundManagement {\n        address sender;\n        bool fromInternalBalance;\n        address payable recipient;\n        bool toInternalBalance;\n    }\n\n    function batchSwap(\n        SwapKind kind,\n        BatchSwapStep[] memory swaps,\n        IAsset[] memory assets,\n        FundManagement memory funds,\n        int256[] memory limits,\n        uint256 deadline\n    ) external payable returns (int256[] memory);\n}\n\ninterface IAsset {}"},{"file_path":"contracts/IERC4626.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4626.sol)\n\npragma solidity ^0.8.15;\n\nimport {IERC20} from \"./IERC20.sol\";\nimport {IERC20Metadata} from \"./IERC20Metadata.sol\";\n\n/**\n * @dev Interface of the ERC-4626 \"Tokenized Vault Standard\", as defined in\n * https://eips.ethereum.org/EIPS/eip-4626[ERC-4626].\n */\ninterface IERC4626 is IERC20, IERC20Metadata {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n\n    event Withdraw(\n        address indexed sender,\n        address indexed receiver,\n        address indexed owner,\n        uint256 assets,\n        uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}"},{"file_path":"contracts/CometExtAssetList.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometExt.sol\";\n\ncontract CometExtAssetList is CometExt {\n\n    /// @notice The address of the asset list factory\n    address immutable public assetListFactory;\n\n    /**\n     * @notice Construct a new protocol instance\n     * @param config The mapping of initial/constant parameters\n     * @param assetListFactoryAddress The address of the asset list factory\n     **/\n    constructor(ExtConfiguration memory config, address assetListFactoryAddress) CometExt(config) {\n        assetListFactory = assetListFactoryAddress;\n    }\n    \n    uint8 internal constant MAX_ASSETS_FOR_ASSET_LIST = 24;\n\n    function maxAssets() override external pure returns (uint8) { return MAX_ASSETS_FOR_ASSET_LIST; }\n}"},{"file_path":"contracts/InstitutionalComet.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometWithExtendedAssetList.sol\";\n\n/**\n * ┌──────────────────────────────────────────────────────────────────────────────────────────┐\n * |   Market-specific terms apply. Review the                                                │\n * │   Institutional Market Supplemental Terms:                                               │\n * │   https://www.compound.xyz/terms-of-service#usdc-institutional-market-terms-of-service   │\n * └──────────────────────────────────────────────────────────────────────────────────────────┘\n *\n * @title InstitutionalComet\n * @dev Inherits the full behaviour of {CometWithExtendedAssetList}\n */\ncontract InstitutionalComet is CometWithExtendedAssetList {\n    /**\n     * @notice Construct a new Institutional Comet instance\n     **/\n    constructor(Configuration memory config) CometWithExtendedAssetList(config) {}\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}"},{"file_path":"contracts/test/CometHarnessInterfaceExtendedAssetList.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../CometInterface.sol\";\n\nabstract contract CometHarnessInterfaceExtendedAssetList is CometInterface {\n    function accrue() virtual external;\n    function getNow() virtual external view returns (uint40);\n    function setNow(uint now_) virtual external;\n    function setTotalsBasic(TotalsBasic memory totals) virtual external;\n    function setTotalsCollateral(address asset, TotalsCollateral memory totals) virtual external;\n    function setBasePrincipal(address account, int104 principal) virtual external;\n    function setCollateralBalance(address account, address asset, uint128 balance) virtual external;\n    function updateAssetsInExternal(address account, address asset, uint128 initialUserBalance, uint128 finalUserBalance) virtual external;\n    function getAssetList(address account) virtual external view returns (address[] memory);\n    function assetList() virtual external view returns (address);\n    function isLendersWithdrawPaused() virtual external view returns (bool);\n    function isBorrowersWithdrawPaused() virtual external view returns (bool);\n    function isCollateralAssetWithdrawPaused(uint24 assetIndex)  virtual external view returns (bool);\n    function isCollateralSupplyPaused() virtual external view returns (bool);\n    function isBaseSupplyPaused() virtual external view returns (bool);\n    function isCollateralAssetSupplyPaused(uint24 assetIndex) virtual external view returns (bool);\n    function isLendersTransferPaused() virtual external view returns (bool);\n    function isBorrowersTransferPaused() virtual external view returns (bool);\n    function isCollateralAssetTransferPaused(uint24 assetIndex) virtual external view returns (bool);\n    function isCollateralTransferPaused() virtual external view returns (bool);\n    function isCollateralWithdrawPaused() virtual external view returns (bool);\n    function MAX_SUPPORTED_UTILIZATION() virtual external view returns (uint256);\n    function isCollateralDeactivated(uint24 assetIndex) virtual external view returns (bool);\n}\n"},{"file_path":"contracts/vendor/renzo/IBalancerRateProvider.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBalancerRateProvider {\n  function getRate() external view returns (uint256);\n}\n"},{"file_path":"contracts/pricefeeds/ReverseMultiplicativePriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title Reverse multiplicative price feed\n * @notice A custom price feed that multiplies the price from one price feed and the inverse price from another price feed and returns the result\n * @dev for example if we need tokenX to eth, but there is only tokenX to usd, we can use this price feed to get tokenX to eth: tokenX to usd * reversed(eth to usd)\n * @author Compound\n */\ncontract ReverseMultiplicativePriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error BadDecimals();\n    error InvalidInt256();\n\n    /// @notice Version of the price feed\n    uint public constant VERSION = 1;\n\n    /// @notice Description of the price feed\n    string public override description;\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Chainlink price feed A\n    address public immutable priceFeedA;\n\n    /// @notice Chainlink price feed B\n    address public immutable priceFeedB;\n\n    /// @notice Price feed A scale\n    int public immutable priceFeedAScale;\n\n    /// @notice Price feed B scale\n    int public immutable priceFeedBScale;\n\n    /// @notice Scale of this price feed\n    int public immutable priceFeedScale;\n\n    /**\n     * @notice Construct a new reverse multiplicative price feed\n     * @param priceFeedA_ The address of the first price feed to fetch prices from\n     * @param priceFeedB_ The address of the second price feed to fetch prices from that should be reversed\n     * @param decimals_ The number of decimals for the returned prices\n     * @param description_ The description of the price feed\n     **/\n    constructor(address priceFeedA_, address priceFeedB_, uint8 decimals_, string memory description_) {\n        priceFeedA = priceFeedA_;\n        priceFeedB = priceFeedB_;\n        uint8 priceFeedADecimals = AggregatorV3Interface(priceFeedA_).decimals();\n        uint8 priceFeedBDecimals = AggregatorV3Interface(priceFeedB_).decimals();\n        priceFeedAScale = signed256(10 ** (priceFeedADecimals));\n        priceFeedBScale = signed256(10 ** (priceFeedBDecimals));\n\n        if (decimals_ > 18) revert BadDecimals();\n        decimals = decimals_;\n        description = description_;\n        priceFeedScale = int256(10 ** decimals);\n    }\n\n    /**\n     * @notice Calculates the latest round data using data from the two price feeds\n     * @return roundId Round id from price feed B\n     * @return answer Latest price\n     * @return startedAt Timestamp when the round was started; passed on from price feed B\n     * @return updatedAt Timestamp when the round was last updated; passed on from price feed B\n     * @return answeredInRound Round id in which the answer was computed; passed on from price feed B\n     * @dev Note: Only the `answer` really matters for downstream contracts that use this price feed (e.g. Comet)\n     **/\n    function latestRoundData() override external view returns (uint80, int256, uint256, uint256, uint80) {\n        (, int256 priceA, , , ) = AggregatorV3Interface(priceFeedA).latestRoundData();\n        (uint80 roundId_, int256 priceB, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(priceFeedB).latestRoundData();\n\n        if (priceA <= 0 || priceB <= 0) return (roundId_, 0, startedAt_, updatedAt_, answeredInRound_);\n\n        // int256 price = priceA * (priceFeedBScale/priceB) * priceFeedScale / priceFeedAScale;\n        int256 price = priceA * priceFeedBScale * priceFeedScale / priceB / priceFeedAScale;\n        return (roundId_, price, startedAt_, updatedAt_, answeredInRound_);\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    /**\n     * @notice Price for the latest round\n     * @return The version of the price feed contract\n     **/\n    function version() external pure returns (uint256) {\n        return VERSION;\n    }\n}\n"},{"file_path":"contracts/pricefeeds/ConstantPriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title Constant price feed\n * @notice A custom price feed that always returns a constant price\n * @author Compound\n */\ncontract ConstantPriceFeed is IPriceFeed {\n    /// @notice Version of the price feed\n    uint public constant override version = 1;\n\n    /// @notice Description of the price feed\n    string public constant description = \"Constant price feed\";\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice The constant price\n    int public immutable constantPrice;\n\n    /**\n     * @notice Construct a new scaling price feed\n     * @param decimals_ The number of decimals for the returned prices\n     **/\n    constructor(uint8 decimals_, int256 constantPrice_) {\n        decimals = decimals_;\n        constantPrice = constantPrice_;\n    }\n\n    /**\n     * @notice Price for the latest round\n     * @return roundId Round id from the underlying price feed\n     * @return answer Latest price for the asset (will always be a constant price)\n     * @return startedAt Timestamp when the round was started; passed on from underlying price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from underlying price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed\n     **/\n    function latestRoundData() external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        return (1, constantPrice, block.timestamp, block.timestamp, 1);\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-periphery/contracts/interfaces/IPeripheryImmutableState.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Immutable state\n/// @notice Functions that return immutable state of the router\ninterface IPeripheryImmutableState {\n    /// @return Returns the address of the Uniswap V3 factory\n    function factory() external view returns (address);\n\n    /// @return Returns the address of WETH9\n    function WETH9() external view returns (address);\n}\n"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\npragma abicoder v2;\n\nimport '../../../v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol';\n\n/// @title Router token swapping functionality\n/// @notice Functions for swapping tokens via Uniswap V3\ninterface ISwapRouter is IUniswapV3SwapCallback {\n    struct ExactInputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        address recipient;\n        uint256 deadline;\n        uint256 amountIn;\n        uint256 amountOutMinimum;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// @notice Swaps `amountIn` of one token for as much as possible of another token\n    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata\n    /// @return amountOut The amount of the received token\n    function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);\n\n    struct ExactInputParams {\n        bytes path;\n        address recipient;\n        uint256 deadline;\n        uint256 amountIn;\n        uint256 amountOutMinimum;\n    }\n\n    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata\n    /// @return amountOut The amount of the received token\n    function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);\n\n    struct ExactOutputSingleParams {\n        address tokenIn;\n        address tokenOut;\n        uint24 fee;\n        address recipient;\n        uint256 deadline;\n        uint256 amountOut;\n        uint256 amountInMaximum;\n        uint160 sqrtPriceLimitX96;\n    }\n\n    /// @notice Swaps as little as possible of one token for `amountOut` of another token\n    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata\n    /// @return amountIn The amount of the input token\n    function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);\n\n    struct ExactOutputParams {\n        bytes path;\n        address recipient;\n        uint256 deadline;\n        uint256 amountOut;\n        uint256 amountInMaximum;\n    }\n\n    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)\n    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata\n    /// @return amountIn The amount of the input token\n    function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);\n}\n"},{"file_path":"contracts/bulkers/BaseBulker.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../CometInterface.sol\";\nimport \"../IERC20NonStandard.sol\";\nimport \"../IWETH9.sol\";\n\n/**\n * @dev Interface for claiming rewards from the CometRewards contract\n */\ninterface IClaimable {\n    function claim(address comet, address src, bool shouldAccrue) external;\n\n    function claimTo(address comet, address src, address to, bool shouldAccrue) external;\n}\n\n/**\n * @title Compound's Bulker contract\n * @notice Executes multiple Comet-related actions in a single transaction\n * @author Compound\n * @dev Note: Only intended to be used on EVM chains that have a native token and wrapped native token that implements the IWETH interface\n */\ncontract BaseBulker {\n    /** Custom events **/\n\n    event AdminTransferred(address indexed oldAdmin, address indexed newAdmin);\n\n    /** General configuration constants **/\n\n    /// @notice The admin of the Bulker contract\n    address public admin;\n\n    /// @notice The address of the wrapped representation of the chain's native asset\n    address payable public immutable wrappedNativeToken;\n\n    /** Actions **/\n\n    /// @notice The action for supplying an asset to Comet\n    bytes32 public constant ACTION_SUPPLY_ASSET = \"ACTION_SUPPLY_ASSET\";\n\n    /// @notice The action for supplying a native asset (e.g. ETH on Ethereum mainnet) to Comet\n    bytes32 public constant ACTION_SUPPLY_NATIVE_TOKEN = \"ACTION_SUPPLY_NATIVE_TOKEN\";\n\n    /// @notice The action for transferring an asset within Comet\n    bytes32 public constant ACTION_TRANSFER_ASSET = \"ACTION_TRANSFER_ASSET\";\n\n    /// @notice The action for withdrawing an asset from Comet\n    bytes32 public constant ACTION_WITHDRAW_ASSET = \"ACTION_WITHDRAW_ASSET\";\n\n    /// @notice The action for withdrawing a native asset from Comet\n    bytes32 public constant ACTION_WITHDRAW_NATIVE_TOKEN = \"ACTION_WITHDRAW_NATIVE_TOKEN\";\n\n    /// @notice The action for claiming rewards from the Comet rewards contract\n    bytes32 public constant ACTION_CLAIM_REWARD = \"ACTION_CLAIM_REWARD\";\n\n    /** Custom errors **/\n\n    error InvalidAddress();\n    error InvalidArgument();\n    error FailedToSendNativeToken();\n    error TransferInFailed();\n    error TransferOutFailed();\n    error Unauthorized();\n    error UnhandledAction();\n\n    /**\n     * @notice Construct a new BaseBulker instance\n     * @param admin_ The admin of the Bulker contract\n     * @param wrappedNativeToken_ The address of the wrapped representation of the chain's native asset\n     **/\n    constructor(address admin_, address payable wrappedNativeToken_) {\n        admin = admin_;\n        wrappedNativeToken = wrappedNativeToken_;\n    }\n\n    /**\n     * @notice Fallback for receiving native token. Needed for ACTION_WITHDRAW_NATIVE_TOKEN\n     */\n    receive() external payable {}\n\n    /**\n     * @notice A public function to sweep accidental ERC-20 transfers to this contract\n     * @dev Note: Make sure to check that the asset being swept out is not malicious\n     * @param recipient The address that will receive the swept funds\n     * @param asset The address of the ERC-20 token to sweep\n     */\n    function sweepToken(address recipient, address asset) external {\n        if (msg.sender != admin) revert Unauthorized();\n\n        uint256 balance = IERC20NonStandard(asset).balanceOf(address(this));\n        doTransferOut(asset, recipient, balance);\n    }\n\n    /**\n     * @notice A public function to sweep accidental native token transfers to this contract\n     * @param recipient The address that will receive the swept funds\n     */\n    function sweepNativeToken(address recipient) external {\n        if (msg.sender != admin) revert Unauthorized();\n\n        uint256 balance = address(this).balance;\n        (bool success, ) = recipient.call{ value: balance }(\"\");\n        if (!success) revert FailedToSendNativeToken();\n    }\n\n    /**\n     * @notice Transfers the admin rights to a new address\n     * @param newAdmin The address that will become the new admin\n     */\n    function transferAdmin(address newAdmin) external {\n        if (msg.sender != admin) revert Unauthorized();\n        if (newAdmin == address(0)) revert InvalidAddress();\n\n        address oldAdmin = admin;\n        admin = newAdmin;\n        emit AdminTransferred(oldAdmin, newAdmin);\n    }\n\n    /**\n     * @notice Executes a list of actions in order\n     * @param actions The list of actions to execute in order\n     * @param data The list of calldata to use for each action\n     */\n    function invoke(bytes32[] calldata actions, bytes[] calldata data) external payable {\n        if (actions.length != data.length) revert InvalidArgument();\n\n        uint unusedNativeToken = msg.value;\n        for (uint i = 0; i < actions.length; ) {\n            bytes32 action = actions[i];\n            if (action == ACTION_SUPPLY_ASSET) {\n                (address comet, address to, address asset, uint amount) = abi.decode(data[i], (address, address, address, uint));\n                supplyTo(comet, to, asset, amount);\n            } else if (action == ACTION_SUPPLY_NATIVE_TOKEN) {\n                (address comet, address to, uint amount) = abi.decode(data[i], (address, address, uint));\n                uint256 nativeTokenUsed = supplyNativeTokenTo(comet, to, amount);\n                unusedNativeToken -= nativeTokenUsed;\n            } else if (action == ACTION_TRANSFER_ASSET) {\n                (address comet, address to, address asset, uint amount) = abi.decode(data[i], (address, address, address, uint));\n                transferTo(comet, to, asset, amount);\n            } else if (action == ACTION_WITHDRAW_ASSET) {\n                (address comet, address to, address asset, uint amount) = abi.decode(data[i], (address, address, address, uint));\n                withdrawTo(comet, to, asset, amount);\n            } else if (action == ACTION_WITHDRAW_NATIVE_TOKEN) {\n                (address comet, address to, uint amount) = abi.decode(data[i], (address, address, uint));\n                withdrawNativeTokenTo(comet, to, amount);\n            } else if (action == ACTION_CLAIM_REWARD) {\n                (address comet, address rewards, address src, bool shouldAccrue) = abi.decode(data[i], (address, address, address, bool));\n                claimReward(comet, rewards, src, shouldAccrue);\n            } else {\n                handleAction(action, data[i]);\n            }\n            unchecked { i++; }\n        }\n\n        // Refund unused native token back to msg.sender\n        if (unusedNativeToken > 0) {\n            (bool success, ) = msg.sender.call{ value: unusedNativeToken }(\"\");\n            if (!success) revert FailedToSendNativeToken();\n        }\n    }\n\n    /**\n     * @notice Handles any actions not handled by the BaseBulker implementation\n     * @dev Note: Meant to be overridden by contracts that extend BaseBulker and want to support more actions\n     */\n    function handleAction(bytes32 action, bytes calldata data) virtual internal {\n        revert UnhandledAction();\n    }\n\n    /**\n     * @notice Supplies an asset to a user in Comet\n     * @dev Note: This contract must have permission to manage msg.sender's Comet account\n     */\n    function supplyTo(address comet, address to, address asset, uint amount) internal {\n        CometInterface(comet).supplyFrom(msg.sender, to, asset, amount);\n    }\n\n    /**\n     * @notice Wraps the native token and supplies wrapped native token to a user in Comet\n     * @return The amount of the native token wrapped and supplied to Comet\n     * @dev Note: Supports `amount` of `uint256.max` implies max only for base asset\n     */\n    function supplyNativeTokenTo(address comet, address to, uint amount) internal returns (uint256) {\n        uint256 supplyAmount = amount;\n        if (wrappedNativeToken == CometInterface(comet).baseToken()) {\n            if (amount == type(uint256).max)\n                supplyAmount = CometInterface(comet).borrowBalanceOf(msg.sender);\n        }\n        IWETH9(wrappedNativeToken).deposit{ value: supplyAmount }();\n        IWETH9(wrappedNativeToken).approve(comet, supplyAmount);\n        CometInterface(comet).supplyFrom(address(this), to, wrappedNativeToken, supplyAmount);\n        return supplyAmount;\n    }\n\n    /**\n     * @notice Transfers an asset to a user in Comet\n     * @dev Note: This contract must have permission to manage msg.sender's Comet account\n     */\n    function transferTo(address comet, address to, address asset, uint amount) internal {\n        CometInterface(comet).transferAssetFrom(msg.sender, to, asset, amount);\n    }\n\n    /**\n     * @notice Withdraws an asset to a user in Comet\n     * @dev Note: This contract must have permission to manage msg.sender's Comet account\n     */\n    function withdrawTo(address comet, address to, address asset, uint amount) internal {\n        CometInterface(comet).withdrawFrom(msg.sender, to, asset, amount);\n    }\n\n    /**\n     * @notice Withdraws wrapped native token from Comet, unwraps it to the native token, and transfers it to a user\n     * @dev Note: This contract must have permission to manage msg.sender's Comet account\n     * @dev Note: Supports `amount` of `uint256.max` only for the base asset. Should revert for a collateral asset\n     */\n    function withdrawNativeTokenTo(address comet, address to, uint amount) internal {\n        uint256 withdrawAmount = amount;\n        if (wrappedNativeToken == CometInterface(comet).baseToken()) {\n            if (amount == type(uint256).max)\n                withdrawAmount = CometInterface(comet).balanceOf(msg.sender);\n        }\n        CometInterface(comet).withdrawFrom(msg.sender, address(this), wrappedNativeToken, withdrawAmount);\n        IWETH9(wrappedNativeToken).withdraw(withdrawAmount);\n        (bool success, ) = to.call{ value: withdrawAmount }(\"\");\n        if (!success) revert FailedToSendNativeToken();\n    }\n\n    /**\n     * @notice Claims rewards for a user\n     */\n    function claimReward(address comet, address rewards, address src, bool shouldAccrue) internal {\n        IClaimable(rewards).claim(comet, src, shouldAccrue);\n    }\n\n    /**\n     * @notice Similar to ERC-20 transfer, except it properly handles `transferFrom` from non-standard ERC-20 tokens\n     * @param asset The ERC-20 token to transfer in\n     * @param from The address to transfer from\n     * @param amount The amount of the token to transfer\n     * @dev Note: This does not check that the amount transferred in is actually equals to the amount specified (e.g. fee tokens will not revert)\n     * @dev Note: This wrapper 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 {\n        IERC20NonStandard(asset).transferFrom(from, address(this), amount);\n\n        bool success;\n        assembly {\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    }\n\n    /**\n     * @notice Similar to ERC-20 transfer, except it properly handles `transfer` from non-standard ERC-20 tokens\n     * @param asset The ERC-20 token to transfer out\n     * @param to The recipient of the token transfer\n     * @param amount The amount of the token to transfer\n     * @dev Note: This wrapper 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\n        bool success;\n        assembly {\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"},{"file_path":"contracts/marketupdates/ConfiguratorOld.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./../CometFactory.sol\";\nimport \"./../CometConfiguration.sol\";\nimport \"./../ConfiguratorStorage.sol\";\n\n/**\n * @title Compound's Configurator Contract\n * @notice The contract that stores the configuration for Comet proxies\n * @dev This contract is just to simulate the full deployment process of market updates. Should be deleted after the market updates are deployed.\n */\ncontract ConfiguratorOld is ConfiguratorStorage {\n\n    /** Custom events **/\n\n    event AddAsset(address indexed cometProxy, AssetConfig assetConfig);\n    event CometDeployed(address indexed cometProxy, address indexed newComet);\n    event GovernorTransferred(address indexed oldGovernor, address indexed newGovernor);\n    event SetFactory(address indexed cometProxy, address indexed oldFactory, address indexed newFactory);\n    event SetGovernor(address indexed cometProxy, address indexed oldGovernor, address indexed newGovernor);\n    event SetConfiguration(address indexed cometProxy, Configuration oldConfiguration, Configuration newConfiguration);\n    event SetPauseGuardian(address indexed cometProxy, address indexed oldPauseGuardian, address indexed newPauseGuardian);\n    event SetBaseTokenPriceFeed(address indexed cometProxy, address indexed oldBaseTokenPriceFeed, address indexed newBaseTokenPriceFeed);\n    event SetExtensionDelegate(address indexed cometProxy, address indexed oldExt, address indexed newExt);\n    event SetSupplyKink(address indexed cometProxy,uint64 oldKink, uint64 newKink);\n    event SetSupplyPerYearInterestRateSlopeLow(address indexed cometProxy,uint64 oldIRSlopeLow, uint64 newIRSlopeLow);\n    event SetSupplyPerYearInterestRateSlopeHigh(address indexed cometProxy,uint64 oldIRSlopeHigh, uint64 newIRSlopeHigh);\n    event SetSupplyPerYearInterestRateBase(address indexed cometProxy,uint64 oldIRBase, uint64 newIRBase);\n    event SetBorrowKink(address indexed cometProxy,uint64 oldKink, uint64 newKink);\n    event SetBorrowPerYearInterestRateSlopeLow(address indexed cometProxy,uint64 oldIRSlopeLow, uint64 newIRSlopeLow);\n    event SetBorrowPerYearInterestRateSlopeHigh(address indexed cometProxy,uint64 oldIRSlopeHigh, uint64 newIRSlopeHigh);\n    event SetBorrowPerYearInterestRateBase(address indexed cometProxy,uint64 oldIRBase, uint64 newIRBase);\n    event SetStoreFrontPriceFactor(address indexed cometProxy, uint64 oldStoreFrontPriceFactor, uint64 newStoreFrontPriceFactor);\n    event SetBaseTrackingSupplySpeed(address indexed cometProxy, uint64 oldBaseTrackingSupplySpeed, uint64 newBaseTrackingSupplySpeed);\n    event SetBaseTrackingBorrowSpeed(address indexed cometProxy, uint64 oldBaseTrackingBorrowSpeed, uint64 newBaseTrackingBorrowSpeed);\n    event SetBaseMinForRewards(address indexed cometProxy, uint104 oldBaseMinForRewards, uint104 newBaseMinForRewards);\n    event SetBaseBorrowMin(address indexed cometProxy, uint104 oldBaseBorrowMin, uint104 newBaseBorrowMin);\n    event SetTargetReserves(address indexed cometProxy, uint104 oldTargetReserves, uint104 newTargetReserves);\n    event UpdateAsset(address indexed cometProxy, AssetConfig oldAssetConfig, AssetConfig newAssetConfig);\n    event UpdateAssetPriceFeed(address indexed cometProxy, address indexed asset, address oldPriceFeed, address newPriceFeed);\n    event UpdateAssetBorrowCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldBorrowCF, uint64 newBorrowCF);\n    event UpdateAssetLiquidateCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidateCF, uint64 newLiquidateCF);\n    event UpdateAssetLiquidationFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidationFactor, uint64 newLiquidationFactor);\n    event UpdateAssetSupplyCap(address indexed cometProxy, address indexed asset, uint128 oldSupplyCap, uint128 newSupplyCap);\n\n    /** Custom errors **/\n\n    error AlreadyInitialized();\n    error AssetDoesNotExist();\n    error ConfigurationAlreadyExists();\n    error InvalidAddress();\n    error Unauthorized();\n\n    /**\n     * @notice Constructs a new Configurator instance\n     **/\n    constructor() {\n        // Set a high version to prevent the implementation contract from being initialized\n        version = type(uint256).max;\n    }\n\n    /**\n     * @notice Initializes the storage for Configurator\n     * @param governor_ The address of the governor\n     **/\n    function initialize(address governor_) public {\n        if (version != 0) revert AlreadyInitialized();\n        if (governor_ == address(0)) revert InvalidAddress();\n\n        governor = governor_;\n        version = 1;\n    }\n\n    /**\n     * @notice Sets the factory for a Comet proxy\n     * @dev Note: Only callable by governor\n     **/\n    function setFactory(address cometProxy, address newFactory) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldFactory = factory[cometProxy];\n        factory[cometProxy] = newFactory;\n        emit SetFactory(cometProxy, oldFactory, newFactory);\n    }\n\n    /**\n     * @notice Sets the entire Configuration for a Comet proxy\n     * @dev Note: All params can later be updated by the governor except for `baseToken` and `trackingIndexScale`\n     **/\n    function setConfiguration(address cometProxy, Configuration calldata newConfiguration) external {\n        if (msg.sender != governor) revert Unauthorized();\n        Configuration memory oldConfiguration = configuratorParams[cometProxy];\n        if (oldConfiguration.baseToken != address(0) &&\n            (oldConfiguration.baseToken != newConfiguration.baseToken ||\n                oldConfiguration.trackingIndexScale != newConfiguration.trackingIndexScale))\n            revert ConfigurationAlreadyExists();\n\n        configuratorParams[cometProxy] = newConfiguration;\n        emit SetConfiguration(cometProxy, oldConfiguration, newConfiguration);\n    }\n\n    /** Governance setters for Comet-related configuration **/\n\n    function setGovernor(address cometProxy, address newGovernor) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldGovernor = configuratorParams[cometProxy].governor;\n        configuratorParams[cometProxy].governor = newGovernor;\n        emit SetGovernor(cometProxy, oldGovernor, newGovernor);\n    }\n\n    function setPauseGuardian(address cometProxy, address newPauseGuardian) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldPauseGuardian = configuratorParams[cometProxy].pauseGuardian;\n        configuratorParams[cometProxy].pauseGuardian = newPauseGuardian;\n        emit SetPauseGuardian(cometProxy, oldPauseGuardian, newPauseGuardian);\n    }\n\n    function setBaseTokenPriceFeed(address cometProxy, address newBaseTokenPriceFeed) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldBaseTokenPriceFeed = configuratorParams[cometProxy].baseTokenPriceFeed;\n        configuratorParams[cometProxy].baseTokenPriceFeed = newBaseTokenPriceFeed;\n        emit SetBaseTokenPriceFeed(cometProxy, oldBaseTokenPriceFeed, newBaseTokenPriceFeed);\n    }\n\n    function setExtensionDelegate(address cometProxy, address newExtensionDelegate) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldExtensionDelegate = configuratorParams[cometProxy].extensionDelegate;\n        configuratorParams[cometProxy].extensionDelegate = newExtensionDelegate;\n        emit SetExtensionDelegate(cometProxy, oldExtensionDelegate, newExtensionDelegate);\n    }\n\n    function setSupplyKink(address cometProxy, uint64 newSupplyKink) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldSupplyKink = configuratorParams[cometProxy].supplyKink;\n        configuratorParams[cometProxy].supplyKink = newSupplyKink;\n        emit SetSupplyKink(cometProxy, oldSupplyKink, newSupplyKink);\n    }\n\n    function setSupplyPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow;\n        configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow = newSlope;\n        emit SetSupplyPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope);\n    }\n\n    function setSupplyPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh;\n        configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh = newSlope;\n        emit SetSupplyPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope);\n    }\n\n    function setSupplyPerYearInterestRateBase(address cometProxy, uint64 newBase) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldBase = configuratorParams[cometProxy].supplyPerYearInterestRateBase;\n        configuratorParams[cometProxy].supplyPerYearInterestRateBase = newBase;\n        emit SetSupplyPerYearInterestRateBase(cometProxy, oldBase, newBase);\n    }\n\n    function setBorrowKink(address cometProxy, uint64 newBorrowKink) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldBorrowKink = configuratorParams[cometProxy].borrowKink;\n        configuratorParams[cometProxy].borrowKink = newBorrowKink;\n        emit SetBorrowKink(cometProxy, oldBorrowKink, newBorrowKink);\n    }\n\n    function setBorrowPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow;\n        configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow = newSlope;\n        emit SetBorrowPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope);\n    }\n\n    function setBorrowPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh;\n        configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh = newSlope;\n        emit SetBorrowPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope);\n    }\n\n    function setBorrowPerYearInterestRateBase(address cometProxy, uint64 newBase) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldBase = configuratorParams[cometProxy].borrowPerYearInterestRateBase;\n        configuratorParams[cometProxy].borrowPerYearInterestRateBase = newBase;\n        emit SetBorrowPerYearInterestRateBase(cometProxy, oldBase, newBase);\n    }\n\n    function setStoreFrontPriceFactor(address cometProxy, uint64 newStoreFrontPriceFactor) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldStoreFrontPriceFactor = configuratorParams[cometProxy].storeFrontPriceFactor;\n        configuratorParams[cometProxy].storeFrontPriceFactor = newStoreFrontPriceFactor;\n        emit SetStoreFrontPriceFactor(cometProxy, oldStoreFrontPriceFactor, newStoreFrontPriceFactor);\n    }\n\n    function setBaseTrackingSupplySpeed(address cometProxy, uint64 newBaseTrackingSupplySpeed) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldBaseTrackingSupplySpeed = configuratorParams[cometProxy].baseTrackingSupplySpeed;\n        configuratorParams[cometProxy].baseTrackingSupplySpeed = newBaseTrackingSupplySpeed;\n        emit SetBaseTrackingSupplySpeed(cometProxy, oldBaseTrackingSupplySpeed, newBaseTrackingSupplySpeed);\n    }\n\n    function setBaseTrackingBorrowSpeed(address cometProxy, uint64 newBaseTrackingBorrowSpeed) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldBaseTrackingBorrowSpeed = configuratorParams[cometProxy].baseTrackingBorrowSpeed;\n        configuratorParams[cometProxy].baseTrackingBorrowSpeed = newBaseTrackingBorrowSpeed;\n        emit SetBaseTrackingBorrowSpeed(cometProxy, oldBaseTrackingBorrowSpeed, newBaseTrackingBorrowSpeed);\n    }\n\n    function setBaseMinForRewards(address cometProxy, uint104 newBaseMinForRewards) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint104 oldBaseMinForRewards = configuratorParams[cometProxy].baseMinForRewards;\n        configuratorParams[cometProxy].baseMinForRewards = newBaseMinForRewards;\n        emit SetBaseMinForRewards(cometProxy, oldBaseMinForRewards, newBaseMinForRewards);\n    }\n\n    function setBaseBorrowMin(address cometProxy, uint104 newBaseBorrowMin) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint104 oldBaseBorrowMin = configuratorParams[cometProxy].baseBorrowMin;\n        configuratorParams[cometProxy].baseBorrowMin = newBaseBorrowMin;\n        emit SetBaseBorrowMin(cometProxy, oldBaseBorrowMin, newBaseBorrowMin);\n    }\n\n    function setTargetReserves(address cometProxy, uint104 newTargetReserves) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint104 oldTargetReserves = configuratorParams[cometProxy].targetReserves;\n        configuratorParams[cometProxy].targetReserves = newTargetReserves;\n        emit SetTargetReserves(cometProxy, oldTargetReserves, newTargetReserves);\n    }\n\n    function addAsset(address cometProxy, AssetConfig calldata assetConfig) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        configuratorParams[cometProxy].assetConfigs.push(assetConfig);\n        emit AddAsset(cometProxy, assetConfig);\n    }\n\n    function updateAsset(address cometProxy, AssetConfig calldata newAssetConfig) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint assetIndex = getAssetIndex(cometProxy, newAssetConfig.asset);\n        AssetConfig memory oldAssetConfig = configuratorParams[cometProxy].assetConfigs[assetIndex];\n        configuratorParams[cometProxy].assetConfigs[assetIndex] = newAssetConfig;\n        emit UpdateAsset(cometProxy, oldAssetConfig, newAssetConfig);\n    }\n\n    function updateAssetPriceFeed(address cometProxy, address asset, address newPriceFeed) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        address oldPriceFeed = configuratorParams[cometProxy].assetConfigs[assetIndex].priceFeed;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].priceFeed = newPriceFeed;\n        emit UpdateAssetPriceFeed(cometProxy, asset, oldPriceFeed, newPriceFeed);\n    }\n\n    function updateAssetBorrowCollateralFactor(address cometProxy, address asset, uint64 newBorrowCF) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        uint64 oldBorrowCF = configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor = newBorrowCF;\n        emit UpdateAssetBorrowCollateralFactor(cometProxy, asset, oldBorrowCF, newBorrowCF);\n    }\n\n    function updateAssetLiquidateCollateralFactor(address cometProxy, address asset, uint64 newLiquidateCF) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        uint64 oldLiquidateCF = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor = newLiquidateCF;\n        emit UpdateAssetLiquidateCollateralFactor(cometProxy, asset, oldLiquidateCF, newLiquidateCF);\n    }\n\n    function updateAssetLiquidationFactor(address cometProxy, address asset, uint64 newLiquidationFactor) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        uint64 oldLiquidationFactor = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor = newLiquidationFactor;\n        emit UpdateAssetLiquidationFactor(cometProxy, asset, oldLiquidationFactor, newLiquidationFactor);\n    }\n\n    function updateAssetSupplyCap(address cometProxy, address asset, uint128 newSupplyCap) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        uint128 oldSupplyCap = configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap = newSupplyCap;\n        emit UpdateAssetSupplyCap(cometProxy, asset, oldSupplyCap, newSupplyCap);\n    }\n\n    /** Other helpers **/\n\n    /**\n     * @dev Determine index of asset that matches given address\n     */\n    function getAssetIndex(address cometProxy, address asset) public view returns (uint) {\n        AssetConfig[] memory assetConfigs = configuratorParams[cometProxy].assetConfigs;\n        uint numAssets = assetConfigs.length;\n        for (uint i = 0; i < numAssets; ) {\n            if (assetConfigs[i].asset == asset) {\n                return i;\n            }\n            unchecked { i++; }\n        }\n        revert AssetDoesNotExist();\n    }\n\n    /**\n     * @return The currently configured params for a Comet proxy\n     **/\n    function getConfiguration(address cometProxy) external view returns (Configuration memory) {\n        return configuratorParams[cometProxy];\n    }\n\n    /**\n     * @notice Deploy a new Comet implementation using the factory and Configuration for that Comet proxy\n     * @dev Note: Callable by anyone\n     */\n    function deploy(address cometProxy) external returns (address) {\n        address newComet = CometFactory(factory[cometProxy]).clone(configuratorParams[cometProxy]);\n        emit CometDeployed(cometProxy, newComet);\n        return newComet;\n    }\n\n    /**\n     * @notice Transfers the governor rights to a new address\n     */\n    function transferGovernor(address newGovernor) external {\n        if (msg.sender != governor) revert Unauthorized();\n        address oldGovernor = governor;\n        governor = newGovernor;\n        emit GovernorTransferred(oldGovernor, newGovernor);\n    }\n}\n"},{"file_path":"contracts/bridges/polygon/PolygonBridgeReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./IFxMessageProcessor.sol\";\nimport \"../BaseBridgeReceiver.sol\";\n\ncontract PolygonBridgeReceiver is IFxMessageProcessor, BaseBridgeReceiver {\n    error InvalidChild();\n\n    event NewFxChild(address indexed oldFxChild, address indexed newFxChild);\n\n    /// @notice Address of Polygon's bridged message receiver\n    address public fxChild;\n\n    /**\n     * @notice Construct a new PolygonBridgeReceiver instance\n     * @param _fxChild Address of Polygon bridged message receiver\n     **/\n    constructor(address _fxChild) {\n        fxChild = _fxChild;\n    }\n\n    /**\n     * @notice Update the fxChild address\n     * @param newFxChild New value for fxAddress\n     */\n    function changeFxChild(address newFxChild) public {\n        if (msg.sender != localTimelock) revert Unauthorized();\n        address oldFxChild = fxChild;\n        fxChild = newFxChild;\n        emit NewFxChild(oldFxChild, newFxChild);\n    }\n\n    /**\n     * @notice Receive bridged message and enqueue in the Timelock\n     * @param stateId Value provided by fxChild when function is called; ignored\n     * @param rootMessageSender Mainnet address that initiated the bridged message\n     * @param data ABI-encoded data of the bridged message\n     */\n    function processMessageFromRoot(\n        uint256 stateId,\n        address rootMessageSender,\n        bytes calldata data\n    ) public override {\n        if (msg.sender != fxChild) revert InvalidChild();\n        processMessage(rootMessageSender, data);\n    }\n}"},{"file_path":"contracts/IWETH9.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\ninterface IWETH9 {\n    function name() external view returns (string memory);\n\n    function symbol() external view returns (string memory);\n\n    function decimals() external view returns (uint8);\n\n    function balanceOf(address) external view returns (uint);\n\n    function allowance(address, address) external view returns (uint);\n\n    receive() external payable;\n\n    function deposit() external payable;\n\n    function withdraw(uint wad) external;\n\n    function totalSupply() external view returns (uint);\n\n    function approve(address guy, uint wad) external returns (bool);\n\n    function transfer(address dst, uint wad) external returns (bool);\n\n    function transferFrom(address src, address dst, uint wad)\n    external\n    returns (bool);\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Provides functions for deriving a pool address from the factory, tokens, and the fee\nlibrary PoolAddress {\n    bytes32 internal constant POOL_INIT_CODE_HASH = 0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;\n\n    /// @notice The identifying key of the pool\n    struct PoolKey {\n        address token0;\n        address token1;\n        uint24 fee;\n    }\n\n    /// @notice Returns PoolKey: the ordered tokens with the matched fee levels\n    /// @param tokenA The first token of a pool, unsorted\n    /// @param tokenB The second token of a pool, unsorted\n    /// @param fee The fee level of the pool\n    /// @return Poolkey The pool details with ordered token0 and token1 assignments\n    function getPoolKey(\n        address tokenA,\n        address tokenB,\n        uint24 fee\n    ) internal pure returns (PoolKey memory) {\n        if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);\n        return PoolKey({token0: tokenA, token1: tokenB, fee: fee});\n    }\n\n    /// @notice Deterministically computes the pool address given the factory and PoolKey\n    /// @param factory The Uniswap V3 factory contract address\n    /// @param key The PoolKey\n    /// @return pool The contract address of the V3 pool\n    function computeAddress(address factory, PoolKey memory key) internal pure returns (address pool) {\n        require(key.token0 < key.token1);\n        pool = address(\n            uint160(\n                uint256(\n                    keccak256(\n                        abi.encodePacked(\n                            hex'ff',\n                            factory,\n                            keccak256(abi.encode(key.token0, key.token1, key.fee)),\n                            POOL_INIT_CODE_HASH\n                        )\n                    )\n                )\n            )\n        );\n    }\n}"},{"file_path":"contracts/vendor/kelp/ILRTOracle.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\ninterface ILRTOracle {\n    function rsETHPrice() external view returns (uint256);\n} \n"},{"file_path":"contracts/bridges/optimism/IOvmL2CrossDomainMessengerInterface.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\ninterface IOvmL2CrossDomainMessengerInterface {\n    function xDomainMessageSender() external returns (address);\n}\n"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.15;\n\nimport '../interfaces/IPeripheryImmutableState.sol';\n\n/// @title Immutable state\n/// @notice Immutable state used by periphery contracts\nabstract contract PeripheryImmutableState is IPeripheryImmutableState {\n    /// @inheritdoc IPeripheryImmutableState\n    address public immutable override factory;\n    /// @inheritdoc IPeripheryImmutableState\n    address public immutable override WETH9;\n\n    constructor(address _factory, address _WETH9) {\n        factory = _factory;\n        WETH9 = _WETH9;\n    }\n}\n"},{"file_path":"contracts/bulkers/MainnetBulker.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./BaseBulker.sol\";\nimport \"../IWstETH.sol\";\n\n/**\n * @title Compound's Bulker contract for Ethereum mainnet\n * @notice Executes multiple Comet-related actions in a single transaction\n * @author Compound\n */\ncontract MainnetBulker is BaseBulker {\n    /** General configuration constants **/\n\n    /// @notice The address of Lido staked ETH\n    address public immutable steth;\n\n    /// @notice The address of Lido wrapped staked ETH\n    address public immutable wsteth;\n\n    /** Actions **/\n\n    /// @notice The action for supplying staked ETH to Comet\n    bytes32 public constant ACTION_SUPPLY_STETH = \"ACTION_SUPPLY_STETH\";\n\n    /// @notice The action for withdrawing staked ETH from Comet\n    bytes32 public constant ACTION_WITHDRAW_STETH = \"ACTION_WITHDRAW_STETH\";\n\n    /** Custom errors **/\n\n    error UnsupportedBaseAsset();\n\n    /**\n     * @notice Construct a new MainnetBulker instance\n     * @param admin_ The admin of the Bulker contract\n     * @param weth_ The address of wrapped ETH\n     * @param wsteth_ The address of Lido wrapped staked ETH\n     **/\n    constructor(\n        address admin_,\n        address payable weth_,\n        address wsteth_\n    ) BaseBulker(admin_, weth_) {\n        wsteth = wsteth_;\n        steth = IWstETH(wsteth_).stETH();\n    }\n\n    /**\n     * @notice Handles actions specific to the Ethereum mainnet version of Bulker, specifically supplying and withdrawing stETH\n     */\n    function handleAction(bytes32 action, bytes calldata data) override internal {\n        if (action == ACTION_SUPPLY_STETH) {\n            (address comet, address to, uint stETHAmount) = abi.decode(data, (address, address, uint));\n            supplyStEthTo(comet, to, stETHAmount);\n        } else if (action == ACTION_WITHDRAW_STETH) {\n            (address comet, address to, uint wstETHAmount) = abi.decode(data, (address, address, uint));\n            withdrawStEthTo(comet, to, wstETHAmount);\n        } else {\n            revert UnhandledAction();\n        }\n    }\n\n    /**\n     * @notice Wraps stETH to wstETH and supplies to a user in Comet\n     * @dev Note: This contract must have permission to manage msg.sender's Comet account\n     * @dev Note: wstETH base asset is NOT supported\n     */\n    function supplyStEthTo(address comet, address to, uint stETHAmount) internal {\n        if (CometInterface(comet).baseToken() == wsteth) revert UnsupportedBaseAsset();\n\n        doTransferIn(steth, msg.sender, stETHAmount);\n        ERC20(steth).approve(wsteth, stETHAmount);\n        uint wstETHAmount = IWstETH(wsteth).wrap(stETHAmount);\n        ERC20(wsteth).approve(comet, wstETHAmount);\n        CometInterface(comet).supplyFrom(address(this), to, wsteth, wstETHAmount);\n    }\n\n    /**\n     * @notice Withdraws wstETH from Comet, unwraps it to stETH, and transfers it to a user\n     * @dev Note: This contract must have permission to manage msg.sender's Comet account\n     * @dev Note: wstETH base asset is NOT supported\n     * @dev Note: Supports `amount` of `uint256.max` to withdraw all wstETH from Comet\n     */\n    function withdrawStEthTo(address comet, address to, uint stETHAmount) internal {\n        if (CometInterface(comet).baseToken() == wsteth) revert UnsupportedBaseAsset();\n\n        uint wstETHAmount = stETHAmount == type(uint256).max\n            ? CometInterface(comet).collateralBalanceOf(msg.sender, wsteth)\n            : IWstETH(wsteth).getWstETHByStETH(stETHAmount);\n        CometInterface(comet).withdrawFrom(msg.sender, address(this), wsteth, wstETHAmount);\n        uint unwrappedStETHAmount = IWstETH(wsteth).unwrap(wstETHAmount);\n        doTransferOut(steth, to, unwrappedStETHAmount);\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Callback for IUniswapV3PoolActions#swap\n/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface\ninterface IUniswapV3SwapCallback {\n    /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n    /// @dev In the implementation you must pay the pool tokens owed for the swap.\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n    /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n    /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n    /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n    /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n    /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n    function uniswapV3SwapCallback(\n        int256 amount0Delta,\n        int256 amount1Delta,\n        bytes calldata data\n    ) external;\n}\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/pricefeeds/WBTCPriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title WBTC price feed\n * @notice A custom price feed that calculates the price for WBTC / USD\n * @author Compound\n */\ncontract WBTCPriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error BadDecimals();\n    error InvalidInt256();\n\n    /// @notice Version of the price feed\n    uint public constant override version = 1;\n\n    /// @notice Description of the price feed\n    string public constant override description = \"Custom price feed for WBTC / USD\";\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Chainlink WBTC / BTC price feed\n    address public immutable WBTCToBTCPriceFeed;\n\n    /// @notice Chainlink BTC / USD price feed\n    address public immutable BTCToUSDPriceFeed;\n\n    /// @notice Combined scale of the two underlying Chainlink price feeds\n    int public immutable combinedScale;\n\n    /// @notice Scale of this price feed\n    int public immutable priceFeedScale;\n\n    /**\n     * @notice Construct a new WBTC / USD price feed\n     * @param WBTCToBTCPriceFeed_ The address of the WBTC / BTC price feed to fetch prices from\n     * @param BTCToUSDPriceFeed_ The address of the BTC / USD price feed to fetch prices from\n     * @param decimals_ The number of decimals for the returned prices\n     **/\n    constructor(address WBTCToBTCPriceFeed_, address BTCToUSDPriceFeed_, uint8 decimals_) {\n        WBTCToBTCPriceFeed = WBTCToBTCPriceFeed_;\n        BTCToUSDPriceFeed = BTCToUSDPriceFeed_;\n        uint8 WBTCToBTCPriceFeedDecimals = AggregatorV3Interface(WBTCToBTCPriceFeed_).decimals();\n        uint8 BTCToUSDPriceFeedDecimals = AggregatorV3Interface(BTCToUSDPriceFeed_).decimals();\n        combinedScale = signed256(10 ** (WBTCToBTCPriceFeedDecimals + BTCToUSDPriceFeedDecimals));\n\n        if (decimals_ > 18) revert BadDecimals();\n        decimals = decimals_;\n        priceFeedScale = int256(10 ** decimals);\n    }\n\n    /**\n     * @notice WBTC price for the latest round\n     * @return roundId Round id from the BTC / USD price feed\n     * @return answer Latest price for WBTC / USD\n     * @return startedAt Timestamp when the round was started; passed on from the BTC / USD price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from the BTC / USD price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from the BTC / USD price feed\n     **/\n    function latestRoundData() override external view returns (uint80, int256, uint256, uint256, uint80) {\n        (, int256 WBTCToBTCPrice, , , ) = AggregatorV3Interface(WBTCToBTCPriceFeed).latestRoundData();\n        (uint80 roundId_, int256 BTCToUSDPrice, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(BTCToUSDPriceFeed).latestRoundData();\n\n        // We return the round data of the BTC / USD price feed because of its shorter heartbeat (1hr vs 24hr)\n        if (WBTCToBTCPrice <= 0 || BTCToUSDPrice <= 0) return (roundId_, 0, startedAt_, updatedAt_, answeredInRound_);\n\n        int256 price = WBTCToBTCPrice * BTCToUSDPrice * priceFeedScale / combinedScale;\n        return (roundId_, price, startedAt_, updatedAt_, answeredInRound_);\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}"},{"file_path":"contracts/pricefeeds/MultiplicativePriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title Multiplicative price feed\n * @notice A custom price feed that multiplies the prices from two price feeds and returns the result\n * @author Compound\n */\ncontract MultiplicativePriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error BadDecimals();\n    error InvalidInt256();\n\n    /// @notice Version of the price feed\n    uint public constant VERSION = 1;\n\n    /// @notice Description of the price feed\n    string public override description;\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Chainlink price feed A\n    address public immutable priceFeedA;\n\n    /// @notice Chainlink price feed B\n    address public immutable priceFeedB;\n\n    /// @notice Combined scale of the two underlying Chainlink price feeds\n    int public immutable combinedScale;\n\n    /// @notice Scale of this price feed\n    int public immutable priceFeedScale;\n\n    /**\n     * @notice Construct a new multiplicative price feed\n     * @param priceFeedA_ The address of the first price feed to fetch prices from\n     * @param priceFeedB_ The address of the second price feed to fetch prices from\n     * @param decimals_ The number of decimals for the returned prices\n     * @param description_ The description of the price feed\n     **/\n    constructor(address priceFeedA_, address priceFeedB_, uint8 decimals_, string memory description_) {\n        priceFeedA = priceFeedA_;\n        priceFeedB = priceFeedB_;\n        uint8 priceFeedADecimals = AggregatorV3Interface(priceFeedA_).decimals();\n        uint8 priceFeedBDecimals = AggregatorV3Interface(priceFeedB_).decimals();\n        combinedScale = signed256(10 ** (priceFeedADecimals + priceFeedBDecimals));\n\n        if (decimals_ > 18) revert BadDecimals();\n        decimals = decimals_;\n        description = description_;\n        priceFeedScale = int256(10 ** decimals);\n    }\n\n    /**\n     * @notice Calculates the latest round data using data from the two price feeds\n     * @return roundId Round id from price feed B\n     * @return answer Latest price\n     * @return startedAt Timestamp when the round was started; passed on from price feed B\n     * @return updatedAt Timestamp when the round was last updated; passed on from price feed B\n     * @return answeredInRound Round id in which the answer was computed; passed on from price feed B\n     * @dev Note: Only the `answer` really matters for downstream contracts that use this price feed (e.g. Comet)\n     **/\n    function latestRoundData() override external view returns (uint80, int256, uint256, uint256, uint80) {\n        (, int256 priceA, , , ) = AggregatorV3Interface(priceFeedA).latestRoundData();\n        (uint80 roundId_, int256 priceB, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(priceFeedB).latestRoundData();\n\n        if (priceA <= 0 || priceB <= 0) return (roundId_, 0, startedAt_, updatedAt_, answeredInRound_);\n\n        int256 price = priceA * priceB * priceFeedScale / combinedScale;\n        return (roundId_, price, startedAt_, updatedAt_, answeredInRound_);\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    /**\n     * @notice Price for the latest round\n     * @return The version of the price feed contract\n     **/\n    function version() external pure returns (uint256) {\n        return VERSION;\n    }\n}"},{"file_path":"@openzeppelin/contracts/utils/introspection/ERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"contracts/bridges/optimism/OptimismBridgeReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../SweepableBridgeReceiver.sol\";\nimport \"./IOvmL2CrossDomainMessengerInterface.sol\";\n\ncontract OptimismBridgeReceiver is SweepableBridgeReceiver {\n    error InvalidCrossDomainMessenger();\n\n    event NewCrossDomainMessenger(address indexed oldCrossDomainMessenger, address indexed newCrossDomainMessenger);\n\n    address public crossDomainMessenger;\n\n    constructor(address crossDomainMessenger_) {\n        crossDomainMessenger = crossDomainMessenger_;\n    }\n\n    function changeCrossDomainMessenger(address newCrossDomainMessenger) public {\n        if (msg.sender != localTimelock) revert Unauthorized();\n        address oldCrossDomainMessenger = crossDomainMessenger;\n        crossDomainMessenger = newCrossDomainMessenger;\n        emit NewCrossDomainMessenger(oldCrossDomainMessenger, newCrossDomainMessenger);\n    }\n\n    fallback() external payable {\n        if (msg.sender != crossDomainMessenger) revert InvalidCrossDomainMessenger();\n        address messageSender = IOvmL2CrossDomainMessengerInterface(msg.sender).xDomainMessageSender();\n        processMessage(messageSender, msg.data);\n    }\n}"},{"file_path":"contracts/marketupdates/MarketAdminPermissionCheckerInterface.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @dev Interface for interacting with MarketAdminPermissionChecker\n */\ninterface MarketAdminPermissionCheckerInterface {\n\n    /// @notice Error which represents that the caller passed is not market admin\n    error Unauthorized();\n\n    /// @notice Error which represents that the caller passed is market admin, but market admin is paused and can't\n    /// perform market updates\n    error MarketAdminIsPaused();\n\n    /**\n     * @notice Checks if the caller can perform market updates or not.\n     * Throws an error if the callerAddress is not same as market admin, or if the market admin is paused\n     * @param callerAddress The address of the caller\n     */\n    function checkUpdatePermission(address callerAddress) external view;\n}\n"},{"file_path":"contracts/ConfiguratorProxy.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./vendor/proxy/transparent/TransparentUpgradeableProxy.sol\";\n\n/**\n * @dev A TransparentUpgradeableProxy that allows its admin to call its implementation.\n */\ncontract ConfiguratorProxy is TransparentUpgradeableProxy {\n    /**\n     * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n     * optionally initialized with `_data` as explained in {UpgradeableProxy-constructor}.\n     */\n    constructor(address _logic, address _admin, bytes memory _data) payable TransparentUpgradeableProxy(_logic, _admin, _data) {}\n\n    /**\n     * @dev Overrides the TransparentUpgradeableProxy's _beforeFallback so admin can call the implementation.\n     */\n    function _beforeFallback() internal virtual override {}\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Strings.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n    uint8 private constant _ADDRESS_LENGTH = 20;\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            uint256 length = Math.log10(value) + 1;\n            string memory buffer = new string(length);\n            uint256 ptr;\n            /// @solidity memory-safe-assembly\n            assembly {\n                ptr := add(buffer, add(32, length))\n            }\n            while (true) {\n                ptr--;\n                /// @solidity memory-safe-assembly\n                assembly {\n                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n                }\n                value /= 10;\n                if (value == 0) break;\n            }\n            return buffer;\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        unchecked {\n            return toHexString(value, Math.log256(value) + 1);\n        }\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n     */\n    function toHexString(address addr) internal pure returns (string memory) {\n        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n    }\n}\n"},{"file_path":"contracts/live-test/CometLiveTest.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../CometWithExtendedAssetList.sol\";\n\n/**\n * ┌─────────────────────────────────────────────────────────────────────────┐\n * │                                                                         │\n * │   ⚠️  TEST INSTANCE ONLY — DO NOT DEPOSIT REAL FUNDS  ⚠️               │\n * │                                                                         │\n * │   This Comet is deployed exclusively for live, on-chain testing of      │\n * │   protocol features. It carries no guarantees whatsoever: it may be     │\n * │   upgraded, paused, drained, or abandoned at any moment without notice. │\n * │   Any assets supplied here should be considered permanently at risk and │\n * │   potentially unrecoverable. NEVER deposit funds you are not ready to   │\n * │   lose.                                                                 │\n * │                                                                         │\n * │   The DAO has NO control whatsoever over these Comets: no governance,   │\n * │   no pause, no recovery, no upgrades.                                   │\n * │                                                                         │\n * │   The same applies to EVERY Comet deployed from this instance: none of  │\n * │   them are for production use, and users should never deposit into them.│\n * │                                                                         │\n * └─────────────────────────────────────────────────────────────────────────┘\n *\n * @title CometLiveTest\n * @author Woof\n * @notice A test-only Comet instance. See the banner above: real funds must\n *         never be deposited into this market.\n * @dev Inherits the full behaviour of {CometWithExtendedAssetList} and only adds\n *      an immutable {testingPurpose} description that records why\n *      this test instance exists / which feature is currently being exercised.\n */\ncontract CometLiveTest is CometWithExtendedAssetList {\n    /// @notice Description signalling that this Comet is a testing instance and\n    ///         indicating which feature is currently under test.\n    bytes32 internal immutable testingPurpose32;\n\n    /**\n     * @notice Construct a test-only Comet instance.\n     * @param config The mapping of initial/constant parameters (see {CometWithExtendedAssetList}).\n     * @param testingPurpose32_ Description of the feature under test, as a zero-padded\n     **/\n    constructor(Configuration memory config, bytes32 testingPurpose32_)\n        CometWithExtendedAssetList(config)\n    {\n        testingPurpose32 = testingPurpose32_;\n    }\n\n    /**\n     * @notice Get the description of this test instance's purpose\n     * @return The testing purpose as a string\n     */\n    function testingPurpose() external view returns (string memory) {\n        uint8 i;\n        for (i = 0; i < 32; ) {\n            if (testingPurpose32[i] == 0) {\n                break;\n            }\n            unchecked { i++; }\n        }\n        bytes memory testingPurpose_ = new bytes(i);\n        for (uint8 j = 0; j < i; ) {\n            testingPurpose_[j] = testingPurpose32[j];\n            unchecked { j++; }\n        }\n        return string(testingPurpose_);\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolOwnerActions.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissioned pool actions\n/// @notice Contains pool methods that may only be called by the factory owner\ninterface IUniswapV3PoolOwnerActions {\n    /// @notice Set the denominator of the protocol's % share of the fees\n    /// @param feeProtocol0 new protocol fee for token0 of the pool\n    /// @param feeProtocol1 new protocol fee for token1 of the pool\n    function setFeeProtocol(uint8 feeProtocol0, uint8 feeProtocol1) external;\n\n    /// @notice Collect the protocol fee accrued to the pool\n    /// @param recipient The address to which collected protocol fees should be sent\n    /// @param amount0Requested The maximum amount of token0 to send, can be 0 to collect fees in only token1\n    /// @param amount1Requested The maximum amount of token1 to send, can be 0 to collect fees in only token0\n    /// @return amount0 The protocol fee collected in token0\n    /// @return amount1 The protocol fee collected in token1\n    function collectProtocol(\n        address recipient,\n        uint128 amount0Requested,\n        uint128 amount1Requested\n    ) external returns (uint128 amount0, uint128 amount1);\n}\n"},{"file_path":"contracts/bridges/arbitrum/AddressAliasHelper.sol","source_code":"// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npragma solidity 0.8.15;\n\nlibrary AddressAliasHelper {\n    uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n    /// @notice Utility function that converts the address in the L1 that submitted a tx to\n    /// the inbox to the msg.sender viewed in the L2\n    /// @param l1Address the address in the L1 that triggered the tx to L2\n    /// @return l2Address L2 address as viewed in msg.sender\n    function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n        l2Address = address(uint160(l1Address) + offset);\n    }\n\n    /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n    /// address in the L1 that submitted a tx to the inbox\n    /// @param l2Address L2 address as viewed in msg.sender\n    /// @return l1Address the address in the L1 that triggered the tx to L2\n    function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n        l1Address = address(uint160(l2Address) - offset);\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"},{"file_path":"contracts/CometFactory.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./Comet.sol\";\nimport \"./CometConfiguration.sol\";\n\ncontract CometFactory is CometConfiguration {\n    function clone(Configuration calldata config) external returns (address) {\n        return address(new Comet(config));\n    }\n}"},{"file_path":"contracts/test/EvilToken.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./../ERC20.sol\";\nimport \"./../Comet.sol\";\nimport \"./FaucetToken.sol\";\n\n/**\n * @title Malicious ERC20 token\n * @dev FaucetToken that attempts reentrancy attacks\n */\ncontract EvilToken is FaucetToken {\n    enum AttackType {\n        TRANSFER_FROM,\n        WITHDRAW_FROM,\n        SUPPLY_FROM,\n        BUY_COLLATERAL\n    }\n\n    struct ReentryAttack {\n        AttackType attackType;\n        address source;\n        address destination;\n        address asset;\n        uint amount;\n        uint maxCalls;\n    }\n\n    ReentryAttack public attack;\n    uint public numberOfCalls = 0;\n\n    constructor(\n        uint256 _initialAmount,\n        string memory _tokenName,\n        uint8 _decimalUnits,\n        string memory _tokenSymbol\n    ) FaucetToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n        attack = ReentryAttack({\n            attackType: AttackType.TRANSFER_FROM,\n            source: address(this),\n            destination: address(this),\n            asset: address(this),\n            amount: 1e6,\n            maxCalls: type(uint).max\n        });\n    }\n\n    function getAttack() external view returns (ReentryAttack memory) {\n        return attack;\n    }\n\n    function setAttack(ReentryAttack memory attack_) external {\n        attack = attack_;\n    }\n\n    function transfer(address dst, uint256 amount) public override returns (bool) {\n        numberOfCalls++;\n        if (numberOfCalls > attack.maxCalls){\n            return super.transfer(dst, amount);\n        } else {\n            return performAttack(address(this), dst, amount);\n        }\n    }\n\n    function transferFrom(address src, address dst, uint256 amount) public override returns (bool) {\n        numberOfCalls++;\n        if (numberOfCalls > attack.maxCalls) {\n            return super.transferFrom(src, dst, amount);\n        } else {\n            return performAttack(src, dst, amount);\n        }\n    }\n\n    function performAttack(address src, address dst, uint256 amount) internal returns (bool) {\n        ReentryAttack memory reentryAttack = attack;\n       if (reentryAttack.attackType == AttackType.TRANSFER_FROM) {\n            Comet(payable(msg.sender)).transferFrom(\n                reentryAttack.source,\n                reentryAttack.destination,\n                reentryAttack.amount\n            );\n        } else if (reentryAttack.attackType == AttackType.WITHDRAW_FROM) {\n            Comet(payable(msg.sender)).withdrawFrom(\n                reentryAttack.source,\n                reentryAttack.destination,\n                reentryAttack.asset,\n                reentryAttack.amount\n            );\n        } else if (reentryAttack.attackType == AttackType.SUPPLY_FROM) {\n            Comet(payable(msg.sender)).supplyFrom(\n                reentryAttack.source,\n                reentryAttack.destination,\n                reentryAttack.asset,\n                reentryAttack.amount\n            );\n        }  else if (reentryAttack.attackType == AttackType.BUY_COLLATERAL) {\n            Comet(payable(msg.sender)).buyCollateral(\n                reentryAttack.asset,\n                0,\n                reentryAttack.amount,\n                reentryAttack.destination\n            );\n        } else {\n            revert(\"invalid reentry attack\");\n        }\n        return true;\n    }\n\n}"},{"file_path":"contracts/vendor/proxy/ERC1967/ERC1967Proxy.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n    /**\n     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n     *\n     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n     * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n     */\n    constructor(address _logic, bytes memory _data) payable {\n        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n        _upgradeToAndCall(_logic, _data, false);\n    }\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function _implementation() internal view virtual override returns (address impl) {\n        return ERC1967Upgrade._getImplementation();\n    }\n}\n"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolImmutables.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that never changes\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\ninterface IUniswapV3PoolImmutables {\n    /// @notice The contract that deployed the pool, which must adhere to the IUniswapV3Factory interface\n    /// @return The contract address\n    function factory() external view returns (address);\n\n    /// @notice The first of the two tokens of the pool, sorted by address\n    /// @return The token contract address\n    function token0() external view returns (address);\n\n    /// @notice The second of the two tokens of the pool, sorted by address\n    /// @return The token contract address\n    function token1() external view returns (address);\n\n    /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\n    /// @return The fee\n    function fee() external view returns (uint24);\n\n    /// @notice The pool tick spacing\n    /// @dev Ticks can only be used at multiples of this value, minimum of 1 and always positive\n    /// e.g.: a tickSpacing of 3 means ticks can be initialized every 3rd tick, i.e., ..., -6, -3, 0, 3, 6, ...\n    /// This value is an int24 to avoid casting even though it is always positive.\n    /// @return The tick spacing\n    function tickSpacing() external view returns (int24);\n\n    /// @notice The maximum amount of position liquidity that can use any tick in the range\n    /// @dev This parameter is enforced per tick to prevent liquidity from overflowing a uint128 at any point, and\n    /// also prevents out-of-range liquidity from being used to prevent adding in-range liquidity to a pool\n    /// @return The max amount of liquidity per tick\n    function maxLiquidityPerTick() external view returns (uint128);\n}\n"},{"file_path":"contracts/test/CometHarnessInterface.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../CometInterface.sol\";\n\nabstract contract CometHarnessInterface is CometInterface {\n    function accrue() virtual external;\n    function getNow() virtual external view returns (uint40);\n    function setNow(uint now_) virtual external;\n    function setTotalsBasic(TotalsBasic memory totals) virtual external;\n    function setTotalsCollateral(address asset, TotalsCollateral memory totals) virtual external;\n    function setBasePrincipal(address account, int104 principal) virtual external;\n    function setCollateralBalance(address account, address asset, uint128 balance) virtual external;\n    function updateAssetsInExternal(address account, address asset, uint128 initialUserBalance, uint128 finalUserBalance) virtual external;\n    function getAssetList(address account) virtual external view returns (address[] memory);\n}\n"},{"file_path":"contracts/vendor/proxy/transparent/ProxyAdmin.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.15;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n\n    /**\n    * @dev Sets the initial owner who can perform upgrades.\n     */\n    constructor(address initialOwner) Ownable(initialOwner) {}\n\n    /**\n     * @dev Returns the current implementation of `proxy`.\n     *\n     * Requirements:\n     *\n     * - This contract must be the admin of `proxy`.\n     */\n    function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n        // We need to manually run the static call since the getter cannot be flagged as view\n        // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n        (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n        require(success);\n        return abi.decode(returndata, (address));\n    }\n\n    /**\n     * @dev Returns the current admin of `proxy`.\n     *\n     * Requirements:\n     *\n     * - This contract must be the admin of `proxy`.\n     */\n    function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n        // We need to manually run the static call since the getter cannot be flagged as view\n        // bytes4(keccak256(\"admin()\")) == 0xf851a440\n        (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n        require(success);\n        return abi.decode(returndata, (address));\n    }\n\n    /**\n     * @dev Changes the admin of `proxy` to `newAdmin`.\n     *\n     * Requirements:\n     *\n     * - This contract must be the current admin of `proxy`.\n     */\n    function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n        proxy.changeAdmin(newAdmin);\n    }\n\n    /**\n     * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n     *\n     * Requirements:\n     *\n     * - This contract must be the admin of `proxy`.\n     */\n    function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n        proxy.upgradeTo(implementation);\n    }\n\n    /**\n     * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n     * {TransparentUpgradeableProxy-upgradeToAndCall}.\n     *\n     * Requirements:\n     *\n     * - This contract must be the admin of `proxy`.\n     */\n    function upgradeAndCall(\n        TransparentUpgradeableProxy proxy,\n        address implementation,\n        bytes memory data\n    ) public payable virtual onlyOwner {\n        proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n    }\n}\n"},{"file_path":"contracts/vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\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  // getRoundData and latestRoundData should both raise \"No data present\"\n  // if they do not have data to report, instead of returning unset values\n  // which could be misinterpreted as actual reported values.\n  function getRoundData(uint80 _roundId)\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\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}\n"},{"file_path":"contracts/liquidator/OnChainLiquidator.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\nimport \"./vendor/@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol\";\nimport \"./vendor/@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol\";\nimport \"./vendor/@uniswap/v3-periphery/contracts/base/PeripheryImmutableState.sol\";\nimport \"./vendor/@uniswap/v3-periphery/contracts/libraries/PoolAddress.sol\";\nimport \"./vendor/@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol\";\nimport \"./vendor/@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol\";\nimport \"./vendor/@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol\";\n\nimport \"../CometInterface.sol\";\nimport \"../ERC20.sol\";\nimport \"../IWstETH.sol\";\nimport \"./interfaces/IStableSwap.sol\";\nimport \"./interfaces/IUniswapV2Router.sol\";\nimport \"./interfaces/IVault.sol\";\n\n/**\n * @title Compound's on-chain liquidation contract\n * @author Compound\n */\ncontract OnChainLiquidator is IUniswapV3FlashCallback, PeripheryImmutableState, PeripheryPayments {\n    /** Errors */\n    error InsufficientAmountOut(address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut, uint256 amountOutMin, PoolConfig poolConfig);\n    error InvalidArgument();\n    error InsufficientBalance(uint256 available, uint256 required);\n    error InvalidExchange();\n    error InvalidPoolConfig(address swapToken, PoolConfig poolConfig);\n    error Unauthorized();\n\n    /** Events **/\n    event Absorb(address indexed initiator, address[] accounts);\n    event AbsorbWithoutBuyingCollateral();\n    event BuyAndSwap(address indexed tokenIn, address indexed tokenOut, uint256 baseAmountPaid, uint256 assetBalance, uint256 amountOut);\n    event Pay(address indexed token, address indexed payer, address indexed recipient, uint256 value);\n    event Swap(address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut, PoolConfig poolConfig);\n\n    enum Exchange {\n        Uniswap,\n        SushiSwap,\n        Balancer,\n        Curve\n    }\n\n    // XXX make this less gassy; rearrange fields\n    struct PoolConfig {\n        Exchange exchange;      // which exchange the config applies to\n        uint24 uniswapPoolFee;  // fee for the swap pool (e.g. 3000, 500, 100); only applies to Uniswap pool configs\n        bool swapViaWeth;       // whether to swap the asset to WETH before swapping to base token; applies to SushiSwap and Uniswap pool configs\n        bytes32 balancerPoolId; // pool id for the asset pair; only applies to Balancer pool configs\n        address curvePool;      // address of target Curve pool; only applies to Curve pool configs\n    }\n\n    /** OnChainLiquidator immutables **/\n\n    /// @notice Balancer Vault used for token exchange\n    address public immutable balancerVault;\n\n    /// @notice SushiSwap router used for token exchange\n    address public immutable sushiSwapRouter;\n\n    /// @notice Uniswap router used for token exchange\n    address public immutable uniswapRouter;\n\n    /// @notice Lido Staked Ether 2.0 address\n    address public immutable stEth;\n\n    /// @notice Wrapped liquid staked Ether 2.0 address\n    address public immutable wstEth;\n\n    /** OnChainLiquidator configuration constants **/\n\n    /// @notice Address used by Curve to represent null\n    address public constant NULL_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n    /// @notice The scale for asset price calculations\n    uint256 public constant QUOTE_PRICE_SCALE = 1e18;\n\n    /// @notice The asset pool configurations\n    mapping(address => PoolConfig) public poolConfigs;\n\n    /**\n     * @notice Construct a new liquidator instance\n     * @param balancerVault_ Address of Balancer Vault\n     * @param sushiSwapRouter_ Address of SushiSwap Router\n     * @param uniswapRouter_ Address of Uniswap Router\n     * @param uniswapV3Factory_ Address of Uniswap V3 Factory\n     * @param stEth_ Address of stETH contract\n     * @param wstEth_ Address of wstETH contract\n     * @param WETH9_ Address of WETH9\n     **/\n    constructor(\n        address balancerVault_,\n        address sushiSwapRouter_,\n        address uniswapRouter_,\n        address uniswapV3Factory_,\n        address stEth_,\n        address wstEth_,\n        address WETH9_\n    ) PeripheryImmutableState(uniswapV3Factory_, WETH9_) {\n        balancerVault = balancerVault_;\n        sushiSwapRouter = sushiSwapRouter_;\n        uniswapRouter = uniswapRouter_;\n        stEth = stEth_;\n        wstEth = wstEth_;\n    }\n\n    /**\n     * @notice Calls the pools flash function with data needed in `uniswapV3FlashCallback`\n     * @param comet Instance of Comet to liquidate from\n     * @param liquidatableAccounts List of addresses where Comet.isLiquidatable(address) is true\n     * @param assets List of Comet collateral assets to buy and sell\n     * @param poolConfigs List of PoolConfig structs for each asset in `assets`; determines which exchange to use when swapping\n     * @param maxAmountsToPurchase Max amount of each asset to attempt to buy and sell\n     * @param flashLoanPairToken Address used (in combination with Comet base asset) to find the Uniswap pool to request flash loan from (e.g. USDC/DAI/500)\n     * @param flashLoanPoolFee Pool fee of the Uniswap pool to request flash loan from (e.g. USDC/DAI/500)\n     * @param liquidationThreshold Minimum amount (in terms of Comet base token) to attempt to buy/sell\n     */\n    function absorbAndArbitrage(\n        address comet,\n        address[] calldata liquidatableAccounts,\n        address[] calldata assets,\n        PoolConfig[] calldata poolConfigs,\n        uint[] calldata maxAmountsToPurchase,\n        address flashLoanPairToken,\n        uint24 flashLoanPoolFee,\n        uint liquidationThreshold\n    ) external {\n        if (poolConfigs.length != assets.length) revert InvalidArgument();\n        if (maxAmountsToPurchase.length != assets.length) revert InvalidArgument();\n\n        // Absorb Comet underwater accounts\n        CometInterface(comet).absorb(msg.sender, liquidatableAccounts);\n        emit Absorb(msg.sender, liquidatableAccounts);\n\n        uint256 flashLoanAmount = 0;\n        uint256[] memory assetBaseAmounts = new uint256[](assets.length);\n\n        for (uint8 i = 0; i < assets.length; i++) {\n            ( , uint256 collateralBalanceInBase) = purchasableBalanceOfAsset(\n                comet,\n                assets[i],\n                maxAmountsToPurchase[i]\n            );\n            if (collateralBalanceInBase > liquidationThreshold) {\n                flashLoanAmount += collateralBalanceInBase;\n                assetBaseAmounts[i] = collateralBalanceInBase;\n            }\n        }\n\n        // if there is nothing to buy, just absorb the accounts\n        if (flashLoanAmount == 0) {\n            emit AbsorbWithoutBuyingCollateral();\n            return;\n        }\n\n        address poolToken0 = flashLoanPairToken;\n        address poolToken1 = CometInterface(comet).baseToken();\n        bool reversedPair = poolToken0 > poolToken1;\n        // Use Uniswap approach to determining order of tokens https://github.com/Uniswap/v3-periphery/blob/main/contracts/libraries/PoolAddress.sol#L20-L27\n        if (reversedPair) (poolToken0, poolToken1) = (poolToken1, poolToken0);\n\n        // Find the desired Uniswap pool to borrow base token from, for ex DAI-USDC\n        PoolAddress.PoolKey memory poolKey =\n            PoolAddress.PoolKey({token0: poolToken0, token1: poolToken1, fee: flashLoanPoolFee});\n        IUniswapV3Pool pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\n\n        pool.flash(\n            address(this),\n            reversedPair ? flashLoanAmount : 0,\n            reversedPair ? 0 : flashLoanAmount,\n            abi.encode(\n                FlashCallbackData({\n                    comet: comet,\n                    flashLoanAmount: flashLoanAmount,\n                    recipient: msg.sender,\n                    poolKey: poolKey,\n                    assets: assets,\n                    assetBaseAmounts: assetBaseAmounts,\n                    poolConfigs: poolConfigs\n                })\n            )\n        );\n    }\n\n    struct FlashCallbackData {\n        address comet;\n        uint256 flashLoanAmount;\n        address recipient;\n        PoolAddress.PoolKey poolKey;\n        address[] assets;\n        uint256[] assetBaseAmounts;\n        PoolConfig[] poolConfigs;\n    }\n\n    /**\n     * @notice Uniswap flashloan callback\n     * @param fee0 The fee for borrowing token0 from pool\n     * @param fee1 The fee for borrowing token1 from pool\n     * @param data The encoded data passed from loan initiation function\n     */\n    function uniswapV3FlashCallback(\n        uint256 fee0,\n        uint256 fee1,\n        bytes calldata data\n    ) external override {\n        // Verify uniswap callback, recommended security measure\n        FlashCallbackData memory flashCallbackData = abi.decode(data, (FlashCallbackData));\n        CallbackValidation.verifyCallback(factory, flashCallbackData.poolKey);\n\n        address[] memory assets = flashCallbackData.assets;\n\n        address baseToken = CometInterface(flashCallbackData.comet).baseToken();\n\n        // Allow Comet protocol to withdraw USDC (base token) for collateral purchase\n        TransferHelper.safeApprove(baseToken, address(flashCallbackData.comet), flashCallbackData.flashLoanAmount);\n\n        uint256 totalAmountOut = 0;\n        for (uint i = 0; i < assets.length; i++) {\n            address asset = assets[i];\n            uint256 assetBaseAmount = flashCallbackData.assetBaseAmounts[i];\n\n            if (assetBaseAmount == 0) continue;\n\n            CometInterface(flashCallbackData.comet).buyCollateral(asset, 0, assetBaseAmount, address(this));\n\n            uint256 assetBalance = ERC20(asset).balanceOf(address(this));\n\n            uint256 amountOut = swapCollateral(\n                flashCallbackData.comet,\n                asset,\n                assetBaseAmount,\n                flashCallbackData.poolConfigs[i]\n            );\n\n            emit BuyAndSwap(asset, baseToken, assetBaseAmount, assetBalance, amountOut);\n\n            totalAmountOut += amountOut;\n        }\n\n        address recipient = flashCallbackData.recipient;\n        uint256 totalAmountOwed = flashCallbackData.flashLoanAmount + fee0 + fee1;\n        uint256 balance = ERC20(baseToken).balanceOf(address(this));\n\n        if (totalAmountOwed > balance) {\n            revert InsufficientBalance(balance, totalAmountOwed);\n        }\n\n        TransferHelper.safeApprove(baseToken, address(this), totalAmountOwed);\n\n        // Repay the loan\n        if (totalAmountOwed > 0) {\n            pay(baseToken, address(this), msg.sender, totalAmountOwed);\n            emit Pay(baseToken, address(this), msg.sender, totalAmountOwed);\n        }\n\n        uint256 remainingBalance = ERC20(baseToken).balanceOf(address(this));\n\n        // If profitable, pay profits to the original caller\n        if (remainingBalance > 0) {\n            TransferHelper.safeApprove(baseToken, address(this), remainingBalance);\n            pay(baseToken, address(this), recipient, remainingBalance);\n            emit Pay(baseToken, address(this), recipient, remainingBalance);\n        }\n    }\n\n    /**\n     * @dev Returns lesser of two values\n     */\n    function min(uint256 a, uint256 b) internal view returns (uint256) {\n        return a <= b ? a : b;\n    }\n\n    function purchasableBalanceOfAsset(address comet, address asset, uint maxCollateralToPurchase) internal returns (uint256, uint256) {\n        uint256 collateralBalance = CometInterface(comet).getCollateralReserves(asset);\n\n        collateralBalance = min(collateralBalance, maxCollateralToPurchase);\n\n        uint256 baseScale = CometInterface(comet).baseScale();\n\n        uint256 quotePrice = CometInterface(comet).quoteCollateral(asset, QUOTE_PRICE_SCALE * baseScale);\n        uint256 collateralBalanceInBase = baseScale * QUOTE_PRICE_SCALE * collateralBalance / quotePrice;\n\n        return (collateralBalance, collateralBalanceInBase);\n    }\n\n    function swapCollateral(\n        address comet,\n        address asset,\n        uint256 amountOutMin,\n        PoolConfig memory poolConfig\n    ) internal returns (uint256) {\n        if (poolConfig.exchange == Exchange.Uniswap) {\n            return swapViaUniswap(comet, asset, amountOutMin, poolConfig);\n        } else if (poolConfig.exchange == Exchange.SushiSwap) {\n            return swapViaSushiSwap(comet, asset, amountOutMin, poolConfig);\n        } else if (poolConfig.exchange == Exchange.Balancer) {\n            return swapViaBalancer(comet, asset, amountOutMin, poolConfig);\n        } else if (poolConfig.exchange == Exchange.Curve) {\n            return swapViaCurve(comet, asset, amountOutMin, poolConfig);\n        } else {\n            revert InvalidExchange();\n        }\n    }\n\n    /**\n     * @dev Swaps the given asset to USDC (base token) using Uniswap pools\n     */\n    function swapViaUniswap(address comet, address asset, uint256 amountOutMin, PoolConfig memory poolConfig) internal returns (uint256) {\n        uint256 swapAmount = ERC20(asset).balanceOf(address(this));\n        // Safety check, make sure residue balance in protocol is ignored\n        if (swapAmount == 0) return 0;\n\n        uint24 poolFee = poolConfig.uniswapPoolFee;\n\n        if (poolFee == 0) {\n            revert InvalidPoolConfig(asset, poolConfig);\n        }\n\n        address swapToken = asset;\n\n        address baseToken = CometInterface(comet).baseToken();\n\n        TransferHelper.safeApprove(asset, address(uniswapRouter), swapAmount);\n        // For low liquidity asset, swap it to ETH first\n        if (poolConfig.swapViaWeth) {\n            uint256 swapAmountNew = ISwapRouter(uniswapRouter).exactInputSingle(\n                ISwapRouter.ExactInputSingleParams({\n                    tokenIn: asset,\n                    tokenOut: WETH9,\n                    fee: poolFee,\n                    recipient: address(this),\n                    deadline: block.timestamp,\n                    amountIn: swapAmount,\n                    amountOutMinimum: 0,\n                    sqrtPriceLimitX96: 0\n                })\n            );\n            emit Swap(asset, WETH9, swapAmount, swapAmountNew, poolConfig);\n            swapAmount = swapAmountNew;\n            swapToken = WETH9;\n            poolFee = 500; // XXX move into constant\n\n            TransferHelper.safeApprove(WETH9, address(uniswapRouter), swapAmount);\n        }\n\n        // Swap asset or received ETH to base asset\n        uint256 amountOut = ISwapRouter(uniswapRouter).exactInputSingle(\n            ISwapRouter.ExactInputSingleParams({\n                tokenIn: swapToken,\n                tokenOut: baseToken,\n                fee: poolFee,\n                recipient: address(this),\n                deadline: block.timestamp,\n                amountIn: swapAmount,\n                amountOutMinimum: 0,\n                sqrtPriceLimitX96: 0\n            })\n        );\n\n        // we do a manual check against `amountOutMin` (instead of specifying an\n        // `amountOutMinimum` in the swap) so we can provide better information\n        // in the error message\n        if (amountOut < amountOutMin) {\n            revert InsufficientAmountOut(swapToken, baseToken, swapAmount, amountOut, amountOutMin, poolConfig);\n        }\n\n        emit Swap(swapToken, baseToken, swapAmount, amountOut, poolConfig);\n\n        return amountOut;\n    }\n\n    /**\n     * @dev Swaps the given asset to USDC (base token) using Sushi Swap pools\n     */\n    function swapViaSushiSwap(address comet, address asset, uint256 amountOutMin, PoolConfig memory poolConfig) internal returns (uint256) {\n        uint256 swapAmount = ERC20(asset).balanceOf(address(this));\n        // Safety check, make sure residue balance in protocol is ignored\n        if (swapAmount == 0) return 0;\n\n        address swapToken = asset;\n\n        address baseToken = CometInterface(comet).baseToken();\n\n        TransferHelper.safeApprove(asset, sushiSwapRouter, swapAmount);\n\n        address[] memory path;\n        if (poolConfig.swapViaWeth) {\n            path = new address[](3);\n            path[0] = swapToken;\n            path[1] = WETH9;\n            path[2] = baseToken;\n        } else {\n            path = new address[](2);\n            path[0] = swapToken;\n            path[1] = baseToken;\n        }\n\n        uint256[] memory amounts = IUniswapV2Router(sushiSwapRouter).swapExactTokensForTokens(\n            swapAmount,     // amountIn\n            0,              // amountOutMin\n            path,           // path\n            address(this),  // to\n            block.timestamp // deadline\n        );\n        uint256 amountOut = amounts[amounts.length - 1];\n\n        // we do a manual check against `amountOutMin` (instead of specifying an\n        // `amountOutMinimum` in the swap) so we can provide better information\n        // in the error message\n        if (amountOut < amountOutMin) {\n            revert InsufficientAmountOut(swapToken, baseToken, swapAmount, amountOut, amountOutMin, poolConfig);\n        }\n\n        emit Swap(swapToken, baseToken, swapAmount, amountOut, poolConfig);\n\n        return amountOut;\n    }\n\n    function swapViaBalancer(address comet, address asset, uint256 amountOutMin, PoolConfig memory poolConfig) internal returns (uint256) {\n        uint256 swapAmount = ERC20(asset).balanceOf(address(this));\n        // Safety check, make sure residue balance in protocol is ignored\n        if (swapAmount == 0) return 0;\n\n        address swapToken = asset;\n\n        address baseToken = CometInterface(comet).baseToken();\n\n        TransferHelper.safeApprove(asset, address(balancerVault), swapAmount);\n\n        int256[] memory limits = new int256[](2);\n        limits[0] = type(int256).max;\n        limits[1] = type(int256).max;\n\n        IAsset[] memory assets = new IAsset[](2);\n        assets[0] = IAsset(asset);\n        assets[1] = IAsset(baseToken);\n\n        IVault.BatchSwapStep[] memory steps = new IVault.BatchSwapStep[](1);\n        steps[0] = IVault.BatchSwapStep({\n            poolId: poolConfig.balancerPoolId,\n            assetInIndex: 0,\n            assetOutIndex: 1,\n            amount: swapAmount,\n            userData: bytes(\"\")\n        });\n\n        int256[] memory assetDeltas = IVault(balancerVault).batchSwap(\n            IVault.SwapKind.GIVEN_IN,\n            steps,\n            assets,\n            IVault.FundManagement({\n                sender: address(this),\n                fromInternalBalance: false,\n                recipient: payable(this),\n                toInternalBalance: false\n            }),\n            limits,\n            block.timestamp\n        );\n\n        int256 signedAmountOut = -assetDeltas[assetDeltas.length - 1];\n\n        if (signedAmountOut < 0) {\n            revert InsufficientAmountOut(swapToken, baseToken, swapAmount, 0, amountOutMin, poolConfig);\n        }\n\n        uint256 amountOut = uint256(signedAmountOut);\n\n        if (amountOut < amountOutMin) {\n            revert InsufficientAmountOut(swapToken, baseToken, swapAmount, amountOut, amountOutMin, poolConfig);\n        }\n\n        emit Swap(swapToken, baseToken, swapAmount, amountOut, poolConfig);\n\n        return amountOut;\n    }\n\n    function swapViaCurve(address comet, address asset, uint256 amountOutMin, PoolConfig memory poolConfig) internal returns (uint256) {\n        uint256 swapAmount = ERC20(asset).balanceOf(address(this));\n        // Safety check, make sure residue balance in protocol is ignored\n        if (swapAmount == 0) return 0;\n\n        address tokenIn = asset;\n\n        // unwrap wstETH\n        if (tokenIn == wstEth) {\n            swapAmount = IWstETH(wstEth).unwrap(swapAmount);\n            tokenIn = stEth;\n        }\n\n        address curvePool = poolConfig.curvePool;\n\n        TransferHelper.safeApprove(tokenIn, address(curvePool), swapAmount);\n\n        address coin0 = IStableSwap(curvePool).coins(0);\n        address coin1 = IStableSwap(curvePool).coins(1);\n\n        if (coin0 != tokenIn && coin1 != tokenIn) {\n            revert InvalidPoolConfig(tokenIn, poolConfig);\n        }\n\n        address tokenOut = CometInterface(comet).baseToken();\n\n        // Curve uses the null address to represent ETH\n        if (coin0 == NULL_ADDRESS || coin1 == NULL_ADDRESS) {\n            tokenOut = NULL_ADDRESS;\n        }\n\n        int128 idxOfTokenIn = coin0 == asset ? int128(0) : int128(1);\n        int128 idxOfTokenOut = idxOfTokenIn == 0 ? int128(1) : int128(0);\n\n        uint amountOut = IStableSwap(curvePool).exchange(\n            idxOfTokenIn,  // i idx of token to send\n            idxOfTokenOut, // j idx of token to receive\n            swapAmount,    // _dx amount of i to be exchanged\n            0              // _min_dy min amount of j to receive\n        );\n\n        if (amountOut < amountOutMin) {\n            revert InsufficientAmountOut(tokenIn, tokenOut, swapAmount, amountOut, amountOutMin, poolConfig);\n        }\n\n        // wrap any received ETH to WETH\n        if (tokenOut == NULL_ADDRESS) {\n            IWETH9(WETH9).deposit{value: amountOut}();\n            amountOut = IWETH9(WETH9).balanceOf(address(this));\n            tokenOut = WETH9;\n        }\n\n        emit Swap(tokenIn, tokenOut, swapAmount, amountOut, poolConfig);\n\n        return amountOut;\n    }\n\n    receive() external payable {}\n}\n"},{"file_path":"contracts/pricefeeds/RateBasedScalingPriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../IPriceFeed.sol\";\nimport \"../IRateProvider.sol\";\n\n/**\n * @title Scaling price feed for rate based oracles\n * @notice A custom price feed that scales up or down the price received from an underlying price feed and returns the result\n * @author Compound\n */\ncontract RateBasedScalingPriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error InvalidInt256();\n    error BadDecimals();\n\n    /// @notice Version of the price feed\n    uint public constant VERSION = 1;\n\n    /// @notice Description of the price feed\n    string public description;\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Underlying price feed where prices are fetched from\n    address public immutable underlyingPriceFeed;\n\n    /// @notice Whether or not the price should be upscaled\n    bool internal immutable shouldUpscale;\n\n    /// @notice The amount to upscale or downscale the price by\n    int256 internal immutable rescaleFactor;\n\n    /**\n     * @notice Construct a new scaling price feed\n     * @param underlyingPriceFeed_ The address of the underlying price feed to fetch prices from\n     * @param decimals_ The number of decimals for the returned prices\n     **/\n    constructor(address underlyingPriceFeed_, uint8 decimals_, uint8 underlyingDecimals_, string memory description_) {\n        underlyingPriceFeed = underlyingPriceFeed_;\n        if (decimals_ > 18) revert BadDecimals();\n        decimals = decimals_;\n        description = description_;\n\n        uint8 priceFeedDecimals = underlyingDecimals_;\n        // Note: Solidity does not allow setting immutables in if/else statements\n        shouldUpscale = priceFeedDecimals < decimals_ ? true : false;\n        rescaleFactor = (shouldUpscale\n            ? signed256(10 ** (decimals_ - priceFeedDecimals))\n            : signed256(10 ** (priceFeedDecimals - decimals_))\n        );\n    }\n\n    /**\n     * @notice Price for the latest round\n     * @return roundId Round id from the underlying price feed\n     * @return answer Latest price for the asset in terms of ETH\n     * @return startedAt Timestamp when the round was started; passed on from underlying price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from underlying price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed\n     **/\n    function latestRoundData() override external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        uint256 rate = IRateProvider(underlyingPriceFeed).getRate();\n        return (1, scalePrice(signed256(rate)), block.timestamp, block.timestamp, 1);\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 scalePrice(int256 price) internal view returns (int256) {\n        int256 scaledPrice;\n        if (shouldUpscale) {\n            scaledPrice = price * rescaleFactor;\n        } else {\n            scaledPrice = price / rescaleFactor;\n        }\n        return scaledPrice;\n    }\n\n    /**\n     * @notice Current version of the price feed\n     * @return The version of the price feed contract\n     **/\n    function version() external pure returns (uint256) {\n        return VERSION;\n    }\n}"},{"file_path":"contracts/test/FaucetWETH.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/canonical-weth/contracts/WETH9.sol\";\n\n/**\n * @title The faucet WETH Test Token\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetWETH is WETH9 {\n    constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) WETH9() {}\n\n    function allocateTo(address _owner, uint256 value) public {\n        balanceOf[_owner] += value;\n        emit Transfer(address(this), _owner, value);\n    }\n}"},{"file_path":"contracts/bridges/arbitrum/ArbitrumBridgeReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../SweepableBridgeReceiver.sol\";\nimport \"./AddressAliasHelper.sol\";\n\ncontract ArbitrumBridgeReceiver is SweepableBridgeReceiver {\n    fallback() external payable {\n        processMessage(AddressAliasHelper.undoL1ToL2Alias(msg.sender), msg.data);\n    }\n}"},{"file_path":"contracts/test/SimpleWstETH.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\ncontract SimpleWstETH {\n    uint8 public constant decimals = 18;\n\n    uint public immutable tokensPerStEth;\n\n    constructor(uint tokensPerStEth_) {\n        tokensPerStEth = tokensPerStEth_;\n    }\n}"},{"file_path":"contracts/test/CometHarnessExtendedAssetList.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../CometWithExtendedAssetList.sol\";\n\ncontract CometHarnessExtendedAssetList is CometWithExtendedAssetList {\n    uint public nowOverride;\n\n    constructor(Configuration memory config) CometWithExtendedAssetList(config) {}\n\n    function getNowInternal() override internal view returns (uint40) {\n        return nowOverride > 0 ? uint40(nowOverride) : super.getNowInternal();\n    }\n\n    function getNow() public view returns (uint40) {\n        return getNowInternal();\n    }\n\n    function setNow(uint now_) external {\n        nowOverride = now_;\n    }\n\n    function setTotalsBasic(TotalsBasic memory totals) external {\n        baseSupplyIndex = totals.baseSupplyIndex;\n        baseBorrowIndex = totals.baseBorrowIndex;\n        trackingSupplyIndex = totals.trackingSupplyIndex;\n        trackingBorrowIndex = totals.trackingBorrowIndex;\n        totalSupplyBase = totals.totalSupplyBase;\n        totalBorrowBase = totals.totalBorrowBase;\n        lastAccrualTime = totals.lastAccrualTime;\n    }\n\n    function setTotalsCollateral(address asset, TotalsCollateral memory totals) external {\n        totalsCollateral[asset] = totals;\n    }\n\n    function setBasePrincipal(address account, int104 principal) external {\n        userBasic[account].principal = principal;\n    }\n\n    function setCollateralBalance(address account, address asset, uint128 balance) external {\n        uint128 oldBalance = userCollateral[account][asset].balance;\n        userCollateral[account][asset].balance = balance;\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\n        updateAssetsIn(account, assetInfo, oldBalance, balance);\n    }\n\n    function updateAssetsInExternal(\n        address account,\n        address asset,\n        uint128 initialUserBalance,\n        uint128 finalUserBalance\n    ) external {\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\n        updateAssetsIn(account, assetInfo, initialUserBalance, finalUserBalance);\n    }\n\n    function getAssetList(address account) external view returns (address[] memory result) {\n        uint16 assetsIn = userBasic[account].assetsIn;\n        uint8 _reserved = userBasic[account]._reserved;\n\n        uint8 count = 0;\n        for (uint8 i = 0; i < numAssets; i++) {\n            if (isInAsset(assetsIn, i, _reserved)) {\n                count++;\n            }\n        }\n\n        result = new address[](count);\n\n        uint j = 0;\n        for (uint8 i = 0; i < numAssets; i++) {\n            if (isInAsset(assetsIn, i, _reserved)) {\n                result[j] = getAssetInfo(i).asset;\n                j++;\n            }\n        }\n\n        return result;\n    }\n\n    function accrue() external {\n        accrueInternal();\n    }\n}"},{"file_path":"contracts/AssetList.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./IPriceFeed.sol\";\nimport \"./IERC20NonStandard.sol\";\nimport \"./CometMainInterface.sol\";\nimport \"./CometCore.sol\";\n\n/**\n * @title Compound's Asset List\n * @author Compound\n */\ncontract AssetList {\n    /// @dev The decimals required for a price feed\n    uint8 internal constant PRICE_FEED_DECIMALS = 8;\n\n    /// @dev The scale for factors\n    uint64 internal constant FACTOR_SCALE = 1e18;\n\n    /// @dev The max value for a collateral factor (1)\n    uint64 internal constant MAX_COLLATERAL_FACTOR = FACTOR_SCALE;\n\n    uint256 internal immutable asset00_a;\n    uint256 internal immutable asset00_b;\n    uint256 internal immutable asset01_a;\n    uint256 internal immutable asset01_b;\n    uint256 internal immutable asset02_a;\n    uint256 internal immutable asset02_b;\n    uint256 internal immutable asset03_a;\n    uint256 internal immutable asset03_b;\n    uint256 internal immutable asset04_a;\n    uint256 internal immutable asset04_b;\n    uint256 internal immutable asset05_a;\n    uint256 internal immutable asset05_b;\n    uint256 internal immutable asset06_a;\n    uint256 internal immutable asset06_b;\n    uint256 internal immutable asset07_a;\n    uint256 internal immutable asset07_b;\n    uint256 internal immutable asset08_a;\n    uint256 internal immutable asset08_b;\n    uint256 internal immutable asset09_a;\n    uint256 internal immutable asset09_b;\n    uint256 internal immutable asset10_a;\n    uint256 internal immutable asset10_b;\n    uint256 internal immutable asset11_a;\n    uint256 internal immutable asset11_b;\n    uint256 internal immutable asset12_a;\n    uint256 internal immutable asset12_b;\n    uint256 internal immutable asset13_a;\n    uint256 internal immutable asset13_b;\n    uint256 internal immutable asset14_a;\n    uint256 internal immutable asset14_b;\n    uint256 internal immutable asset15_a;\n    uint256 internal immutable asset15_b;\n    uint256 internal immutable asset16_a;\n    uint256 internal immutable asset16_b;\n    uint256 internal immutable asset17_a;\n    uint256 internal immutable asset17_b;\n    uint256 internal immutable asset18_a;\n    uint256 internal immutable asset18_b;\n    uint256 internal immutable asset19_a;\n    uint256 internal immutable asset19_b;\n    uint256 internal immutable asset20_a;\n    uint256 internal immutable asset20_b;\n    uint256 internal immutable asset21_a;\n    uint256 internal immutable asset21_b;\n    uint256 internal immutable asset22_a;\n    uint256 internal immutable asset22_b;\n    uint256 internal immutable asset23_a;\n    uint256 internal immutable asset23_b;\n\n    /// @notice The number of assets this contract actually supports\n    uint8 public immutable numAssets;\n    \n    constructor(CometConfiguration.AssetConfig[] memory assetConfigs) {\n        uint8 _numAssets = uint8(assetConfigs.length);\n        numAssets = _numAssets;\n        \n        (asset00_a, asset00_b) = getPackedAssetInternal(assetConfigs, 0);\n        (asset01_a, asset01_b) = getPackedAssetInternal(assetConfigs, 1);\n        (asset02_a, asset02_b) = getPackedAssetInternal(assetConfigs, 2);\n        (asset03_a, asset03_b) = getPackedAssetInternal(assetConfigs, 3);\n        (asset04_a, asset04_b) = getPackedAssetInternal(assetConfigs, 4);\n        (asset05_a, asset05_b) = getPackedAssetInternal(assetConfigs, 5);\n        (asset06_a, asset06_b) = getPackedAssetInternal(assetConfigs, 6);\n        (asset07_a, asset07_b) = getPackedAssetInternal(assetConfigs, 7);\n        (asset08_a, asset08_b) = getPackedAssetInternal(assetConfigs, 8);\n        (asset09_a, asset09_b) = getPackedAssetInternal(assetConfigs, 9);\n        (asset10_a, asset10_b) = getPackedAssetInternal(assetConfigs, 10);\n        (asset11_a, asset11_b) = getPackedAssetInternal(assetConfigs, 11);\n        (asset12_a, asset12_b) = getPackedAssetInternal(assetConfigs, 12);\n        (asset13_a, asset13_b) = getPackedAssetInternal(assetConfigs, 13);\n        (asset14_a, asset14_b) = getPackedAssetInternal(assetConfigs, 14);\n        (asset15_a, asset15_b) = getPackedAssetInternal(assetConfigs, 15);\n        (asset16_a, asset16_b) = getPackedAssetInternal(assetConfigs, 16);\n        (asset17_a, asset17_b) = getPackedAssetInternal(assetConfigs, 17);\n        (asset18_a, asset18_b) = getPackedAssetInternal(assetConfigs, 18);\n        (asset19_a, asset19_b) = getPackedAssetInternal(assetConfigs, 19);\n        (asset20_a, asset20_b) = getPackedAssetInternal(assetConfigs, 20);\n        (asset21_a, asset21_b) = getPackedAssetInternal(assetConfigs, 21);\n        (asset22_a, asset22_b) = getPackedAssetInternal(assetConfigs, 22);\n        (asset23_a, asset23_b) = getPackedAssetInternal(assetConfigs, 23);\n    }\n\n    /**\n     * @dev Checks and gets the packed asset info for storage in 2 variables\n     * - in first variable, the asset address is stored in the lower 160 bits (address can be interpreted as uint160),\n     *      the borrow collateral factor in the next 16 bits,\n     *      the liquidate collateral factor in the next 16 bits,\n     *      and the liquidation factor in the next 16 bits\n     * - in the second variable, the price feed address is stored in the lower 160 bits,\n     *      the asset decimals in the next 8 bits,\n     *      and the supply cap in the next 64 bits\n     * @param assetConfigs The asset configurations\n     * @param i The index of the asset info to get\n     * @return The packed asset info\n     */\n    function getPackedAssetInternal(CometConfiguration.AssetConfig[] memory assetConfigs, uint i) internal view returns (uint256, uint256) {\n        CometConfiguration.AssetConfig memory assetConfig;\n        if (i < assetConfigs.length) {\n            assembly {\n                assetConfig := mload(add(add(assetConfigs, 0x20), mul(i, 0x20)))\n            }\n        } else {\n            return (0, 0);\n        }\n        address asset = assetConfig.asset;\n        address priceFeed = assetConfig.priceFeed;\n        uint8 decimals_ = assetConfig.decimals;\n\n        // Short-circuit if asset is nil\n        if (asset == address(0)) {\n            return (0, 0);\n        }\n\n        // Sanity check price feed and asset decimals\n        if (IPriceFeed(priceFeed).decimals() != PRICE_FEED_DECIMALS) revert CometMainInterface.BadDecimals();\n        if (IERC20NonStandard(asset).decimals() != decimals_) revert CometMainInterface.BadDecimals();\n\n        // Sanity checks for factors ordering: BCF < LCF; LCF <= MAX; LF <= MAX\n        if (assetConfig.borrowCollateralFactor >= assetConfig.liquidateCollateralFactor && assetConfig.borrowCollateralFactor != 0)\n            revert CometMainInterface.BorrowCFTooLarge();\n        if (assetConfig.liquidateCollateralFactor > MAX_COLLATERAL_FACTOR) revert CometMainInterface.LiquidateCFTooLarge();\n        if (assetConfig.liquidationFactor > MAX_COLLATERAL_FACTOR) revert CometMainInterface.LiqPenaltyTooHigh();\n\n        // Valid collateral factor configurations:\n        //  1. Both BCF and LCF are 0 => collateral is fully de-listed\n        //  2. borrowCF=0, liquidateCF>0 => soft de-list (no new borrows, controlled liquidation wind-down)\n        //  3. Both non-zero, properly ordered => active collateral\n        // Invalid: borrowCF>0, liquidateCF=0 => reverts (borrow power without liquidation coverage)\n\n        unchecked {\n            // Keep 4 decimals for each factor\n            uint64 descale = FACTOR_SCALE / 1e4;\n            uint16 borrowCollateralFactor = uint16(assetConfig.borrowCollateralFactor / descale);\n            uint16 liquidateCollateralFactor = uint16(assetConfig.liquidateCollateralFactor / descale);\n            uint16 liquidationFactor = uint16(assetConfig.liquidationFactor / descale);\n\n            // safety check duplicate sanity check on original values to ensure no values skewing after descaling and type conversion\n            if (borrowCollateralFactor >= liquidateCollateralFactor && borrowCollateralFactor != 0) revert CometMainInterface.BorrowCFTooLarge();\n\n            // Keep whole units of asset for supply cap\n            uint64 supplyCap = uint64(assetConfig.supplyCap / (10 ** decimals_));\n\n            uint256 word_a = (uint160(asset) << 0 |\n                              uint256(borrowCollateralFactor) << 160 |\n                              uint256(liquidateCollateralFactor) << 176 |\n                              uint256(liquidationFactor) << 192);\n            uint256 word_b = (uint160(priceFeed) << 0 |\n                              uint256(decimals_) << 160 |\n                              uint256(supplyCap) << 168);\n\n            return (word_a, word_b);\n        }\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) public view returns (CometCore.AssetInfo memory) {\n        if (i >= numAssets) revert CometMainInterface.BadAsset();\n        uint256 word_a;\n        uint256 word_b;\n        if(i == 0){\n            word_a = asset00_a;\n            word_b = asset00_b;\n        }\n        if(i == 1){\n            word_a = asset01_a;\n            word_b = asset01_b;\n        }\n        if(i == 2){\n            word_a = asset02_a;\n            word_b = asset02_b;\n        }\n        if(i == 3){\n            word_a = asset03_a;\n            word_b = asset03_b;\n        }\n        if(i == 4){\n            word_a = asset04_a;\n            word_b = asset04_b;\n        }\n        if(i == 5){\n            word_a = asset05_a;\n            word_b = asset05_b;\n        }\n        if(i == 6){\n            word_a = asset06_a;\n            word_b = asset06_b;\n        }\n        if(i == 7){\n            word_a = asset07_a;\n            word_b = asset07_b;\n        }\n        if(i == 8){\n            word_a = asset08_a;\n            word_b = asset08_b;\n        }\n        if(i == 9){\n            word_a = asset09_a;\n            word_b = asset09_b;\n        }\n        if(i == 10){\n            word_a = asset10_a;\n            word_b = asset10_b;\n        }\n        if(i == 11){\n            word_a = asset11_a;\n            word_b = asset11_b;\n        }\n        if(i == 12){\n            word_a = asset12_a;\n            word_b = asset12_b;\n        }\n        if(i == 13){\n            word_a = asset13_a;\n            word_b = asset13_b;\n        }\n        if(i == 14){\n            word_a = asset14_a;\n            word_b = asset14_b;\n        }\n        if(i == 15){\n            word_a = asset15_a;\n            word_b = asset15_b;\n        }\n        if(i == 16){\n            word_a = asset16_a;\n            word_b = asset16_b;\n        }\n        if(i == 17){\n            word_a = asset17_a;\n            word_b = asset17_b;\n        }\n        if(i == 18){\n            word_a = asset18_a;\n            word_b = asset18_b;\n        }\n        if(i == 19){\n            word_a = asset19_a;\n            word_b = asset19_b;\n        }\n        if(i == 20){\n            word_a = asset20_a;\n            word_b = asset20_b;\n        }\n        if(i == 21){\n            word_a = asset21_a;\n            word_b = asset21_b;\n        }\n        if(i == 22){\n            word_a = asset22_a;\n            word_b = asset22_b;\n        }\n        if(i == 23){\n            word_a = asset23_a;\n            word_b = asset23_b;\n        }\n\n        address asset = address(uint160(word_a & type(uint160).max));\n        uint64 rescale = FACTOR_SCALE / 1e4;\n        uint64 borrowCollateralFactor = uint64(((word_a >> 160) & type(uint16).max) * rescale);\n        uint64 liquidateCollateralFactor = uint64(((word_a >> 176) & type(uint16).max) * rescale);\n        uint64 liquidationFactor = uint64(((word_a >> 192) & type(uint16).max) * rescale);\n\n        address priceFeed = address(uint160(word_b & type(uint160).max));\n        uint8 decimals_ = uint8(((word_b >> 160) & type(uint8).max));\n        uint64 scale = uint64(10 ** decimals_);\n        uint128 supplyCap = uint128(((word_b >> 168) & type(uint64).max) * scale);\n\n        return CometCore.AssetInfo({\n            offset: i,\n            asset: asset,\n            priceFeed: priceFeed,\n            scale: scale,\n            borrowCollateralFactor: borrowCollateralFactor,\n            liquidateCollateralFactor: liquidateCollateralFactor,\n            liquidationFactor: liquidationFactor,\n            supplyCap: supplyCap\n         });\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolState.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that can change\n/// @notice These methods compose the pool's state, and can change with any frequency including multiple times\n/// per transaction\ninterface IUniswapV3PoolState {\n    /// @notice The 0th storage slot in the pool stores many values, and is exposed as a single method to save gas\n    /// when accessed externally.\n    /// @return sqrtPriceX96 The current price of the pool as a sqrt(token1/token0) Q64.96 value\n    /// tick The current tick of the pool, i.e. according to the last tick transition that was run.\n    /// This value may not always be equal to SqrtTickMath.getTickAtSqrtRatio(sqrtPriceX96) if the price is on a tick\n    /// boundary.\n    /// observationIndex The index of the last oracle observation that was written,\n    /// observationCardinality The current maximum number of observations stored in the pool,\n    /// observationCardinalityNext The next maximum number of observations, to be updated when the observation.\n    /// feeProtocol The protocol fee for both tokens of the pool.\n    /// Encoded as two 4 bit values, where the protocol fee of token1 is shifted 4 bits and the protocol fee of token0\n    /// is the lower 4 bits. Used as the denominator of a fraction of the swap fee, e.g. 4 means 1/4th of the swap fee.\n    /// unlocked Whether the pool is currently locked to reentrancy\n    function slot0()\n        external\n        view\n        returns (\n            uint160 sqrtPriceX96,\n            int24 tick,\n            uint16 observationIndex,\n            uint16 observationCardinality,\n            uint16 observationCardinalityNext,\n            uint8 feeProtocol,\n            bool unlocked\n        );\n\n    /// @notice The fee growth as a Q128.128 fees of token0 collected per unit of liquidity for the entire life of the pool\n    /// @dev This value can overflow the uint256\n    function feeGrowthGlobal0X128() external view returns (uint256);\n\n    /// @notice The fee growth as a Q128.128 fees of token1 collected per unit of liquidity for the entire life of the pool\n    /// @dev This value can overflow the uint256\n    function feeGrowthGlobal1X128() external view returns (uint256);\n\n    /// @notice The amounts of token0 and token1 that are owed to the protocol\n    /// @dev Protocol fees will never exceed uint128 max in either token\n    function protocolFees() external view returns (uint128 token0, uint128 token1);\n\n    /// @notice The currently in range liquidity available to the pool\n    /// @dev This value has no relationship to the total liquidity across all ticks\n    function liquidity() external view returns (uint128);\n\n    /// @notice Look up information about a specific tick in the pool\n    /// @param tick The tick to look up\n    /// @return liquidityGross the total amount of position liquidity that uses the pool either as tick lower or\n    /// tick upper,\n    /// liquidityNet how much liquidity changes when the pool price crosses the tick,\n    /// feeGrowthOutside0X128 the fee growth on the other side of the tick from the current tick in token0,\n    /// feeGrowthOutside1X128 the fee growth on the other side of the tick from the current tick in token1,\n    /// tickCumulativeOutside the cumulative tick value on the other side of the tick from the current tick\n    /// secondsPerLiquidityOutsideX128 the seconds spent per liquidity on the other side of the tick from the current tick,\n    /// secondsOutside the seconds spent on the other side of the tick from the current tick,\n    /// initialized Set to true if the tick is initialized, i.e. liquidityGross is greater than 0, otherwise equal to false.\n    /// Outside values can only be used if the tick is initialized, i.e. if liquidityGross is greater than 0.\n    /// In addition, these values are only relative and must be used only in comparison to previous snapshots for\n    /// a specific position.\n    function ticks(int24 tick)\n        external\n        view\n        returns (\n            uint128 liquidityGross,\n            int128 liquidityNet,\n            uint256 feeGrowthOutside0X128,\n            uint256 feeGrowthOutside1X128,\n            int56 tickCumulativeOutside,\n            uint160 secondsPerLiquidityOutsideX128,\n            uint32 secondsOutside,\n            bool initialized\n        );\n\n    /// @notice Returns 256 packed tick initialized boolean values. See TickBitmap for more information\n    function tickBitmap(int16 wordPosition) external view returns (uint256);\n\n    /// @notice Returns the information about a position by the position's key\n    /// @param key The position's key is a hash of a preimage composed by the owner, tickLower and tickUpper\n    /// @return _liquidity The amount of liquidity in the position,\n    /// Returns feeGrowthInside0LastX128 fee growth of token0 inside the tick range as of the last mint/burn/poke,\n    /// Returns feeGrowthInside1LastX128 fee growth of token1 inside the tick range as of the last mint/burn/poke,\n    /// Returns tokensOwed0 the computed amount of token0 owed to the position as of the last mint/burn/poke,\n    /// Returns tokensOwed1 the computed amount of token1 owed to the position as of the last mint/burn/poke\n    function positions(bytes32 key)\n        external\n        view\n        returns (\n            uint128 _liquidity,\n            uint256 feeGrowthInside0LastX128,\n            uint256 feeGrowthInside1LastX128,\n            uint128 tokensOwed0,\n            uint128 tokensOwed1\n        );\n\n    /// @notice Returns data about a specific observation index\n    /// @param index The element of the observations array to fetch\n    /// @dev You most likely want to use #observe() instead of this method to get an observation as of some amount of time\n    /// ago, rather than at a specific index in the array.\n    /// @return blockTimestamp The timestamp of the observation,\n    /// Returns tickCumulative the tick multiplied by seconds elapsed for the life of the pool as of the observation timestamp,\n    /// Returns secondsPerLiquidityCumulativeX128 the seconds per in range liquidity for the life of the pool as of the observation timestamp,\n    /// Returns initialized whether the observation has been initialized and the values are safe to use\n    function observations(uint256 index)\n        external\n        view\n        returns (\n            uint32 blockTimestamp,\n            int56 tickCumulative,\n            uint160 secondsPerLiquidityCumulativeX128,\n            bool initialized\n        );\n}\n"},{"file_path":"contracts/vendor/interfaces/draft-IERC1822.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"},{"file_path":"contracts/test/MockRenzoOracle.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\n/**\n * @title Mock oracle\n * @notice Mock oracle to test the scaling price feed with updated update time\n * @author Compound\n */\ncontract MockRenzoOracle {\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable decimals;\n\n    /// @notice Underlying Chainlink price feed where prices are fetched from\n    address public immutable underlyingPriceFeed;\n\n    /**\n     * @notice Construct a new scaling price feed\n     * @param underlyingPriceFeed_ The address of the underlying price feed to fetch prices from\n     **/\n    constructor(address underlyingPriceFeed_) {\n        underlyingPriceFeed = underlyingPriceFeed_;\n        decimals = AggregatorV3Interface(underlyingPriceFeed_).decimals();\n    }\n\n    /**\n     * @notice Price for the latest round\n     * @return roundId Round id from the underlying price feed\n     * @return answer Latest price for the asset in terms of ETH\n     * @return startedAt Timestamp when the round was started; passed on from underlying price feed\n     * @return updatedAt Current timestamp\n     * @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed\n     **/\n    function latestRoundData() external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        (uint80 roundId_, int256 price, uint256 startedAt_, , uint80 answeredInRound_) = AggregatorV3Interface(underlyingPriceFeed).latestRoundData();\n        return (roundId_, price, startedAt_, block.timestamp, answeredInRound_);\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/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/test/PriceFeedWithRevert.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\ncontract PriceFeedWithRevert is AggregatorV3Interface {\n    string public constant override description = \"Mock Chainlink price aggregator\";\n\n    uint public constant override version = 1;\n\n    uint8 public immutable override decimals;\n\n    uint80 internal roundId;\n    int256 internal answer;\n    uint256 internal startedAt;\n    uint256 internal updatedAt;\n    uint80 internal answeredInRound;\n\n    error Reverted();\n\n    constructor(int answer_, uint8 decimals_) {\n        answer = answer_;\n        decimals = decimals_;\n    }\n\n    function setRoundData(\n        uint80 roundId_,\n        int256 answer_,\n        uint256 startedAt_,\n        uint256 updatedAt_,\n        uint80 answeredInRound_\n    ) public {\n        roundId = roundId_;\n        answer = answer_;\n        startedAt = startedAt_;\n        updatedAt = updatedAt_;\n        answeredInRound = answeredInRound_;\n    }\n\n    function getRoundData(uint80 roundId_) override external view returns (uint80, int256, uint256, uint256, uint80) {\n        return (roundId_, answer, startedAt, updatedAt, answeredInRound);\n    }\n\n    function latestRoundData() override external pure returns (uint80, int256, uint256, uint256, uint80) {\n        revert Reverted();\n    }\n}\n"},{"file_path":"contracts/CometExtInterface.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 Ext Interface\n * @notice An efficient monolithic money market protocol\n * @author Compound\n */\nabstract contract CometExtInterface is CometCore {\n    error BadAmount();\n    error BadNonce();\n    error BadSignatory();\n    error InvalidValueS();\n    error InvalidValueV();\n    error SignatureExpired();\n\n    /**\n     * @dev Error thrown when the caller is not the pause guardian or governor\n     */\n    error OnlyPauseGuardianOrGovernor();\n    /**\n     * @dev Error thrown when the offset status is already set\n     * @param offset The offset that is already set\n     * @param status The status of the offset\n     */\n    error OffsetStatusAlreadySet(uint24 offset, bool status);\n    /**\n     * @dev Error thrown when the collateral asset offset status is already set\n     * @param offset The offset that is already set\n     * @param assetIndex The index of the collateral asset\n     * @param status The status of the offset\n     */\n    error CollateralAssetOffsetStatusAlreadySet(uint24 offset, uint24 assetIndex, bool status);\n    /**\n     * @dev Error thrown when the asset index is invalid\n     */\n    error InvalidAssetIndex();\n    /**\n     * @dev Error thrown when the caller is not the pause guardian\n     */\n    error OnlyPauseGuardian();\n    /**\n     * @dev Error thrown when the caller is not the governor\n     */\n    error OnlyGovernor();\n    /**\n     * @dev Error thrown when the collateral asset is already deactivated\n     * @param assetIndex The index of the collateral asset\n     */\n    error CollateralIsDeactivated(uint24 assetIndex);\n    /**\n     * @dev Error thrown when the collateral asset is already activated\n     * @param assetIndex The index of the collateral asset\n     */\n    error CollateralIsActivated(uint24 assetIndex);\n\n    function allow(address manager, bool isAllowed) virtual external;\n    function allowBySig(address owner, address manager, bool isAllowed, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) virtual external;\n\n    /*//////////////////////////////////////////////////////////////\n                             PAUSE CONTROL\n    //////////////////////////////////////////////////////////////*/\n    /**\n     * @notice Pauses or unpauses the ability for lenders to withdraw their assets.\n     * @param paused Whether to pause (`true`) or unpause (`false`) lenders' withdrawals.\n     */\n    function pauseLendersWithdraw(bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the ability for borrowers to withdraw their assets.\n     * @param paused Whether to pause (`true`) or unpause (`false`) borrowers' withdrawals.\n     */\n    function pauseBorrowersWithdraw(bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the ability to withdraw collateral.\n     * @param paused Whether to pause (`true`) or unpause (`false`) collateral withdrawals.\n     */\n    function pauseCollateralWithdraw(bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the ability to withdraw a specific collateral asset.\n     * @param assetIndex The index of the collateral asset to pause/unpause.\n     * @param paused Whether to pause (`true`) or unpause (`false`) withdrawals for the specified collateral asset.\n     */\n    function pauseCollateralAssetWithdraw(uint24 assetIndex, bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the supply of collateral.\n     * @param paused Whether to pause (`true`) or unpause (`false`) collateral supply actions.\n     */\n    function pauseCollateralSupply(bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the supply of base assets.\n     * @param paused Whether to pause (`true`) or unpause (`false`) base asset supply actions.\n     */\n    function pauseBaseSupply(bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the supply of a specific collateral asset.\n     * @param assetIndex The index of the collateral asset to pause/unpause.\n     * @param paused Whether to pause (`true`) or unpause (`false`) supply actions for the specified collateral asset.\n     */\n    function pauseCollateralAssetSupply(uint24 assetIndex, bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the ability for lenders to transfer their assets.\n     * @param paused Whether to pause (`true`) or unpause (`false`) lenders' transfer actions.\n     */\n    function pauseLendersTransfer(bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the ability for borrowers to transfer their assets.\n     * @param paused Whether to pause (`true`) or unpause (`false`) borrowers' transfer actions.\n     */\n    function pauseBorrowersTransfer(bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the ability to transfer collateral.\n     * @param paused Whether to pause (`true`) or unpause (`false`) collateral transfer actions.\n     */\n    function pauseCollateralTransfer(bool paused) virtual external;\n    /**\n     * @notice Pauses or unpauses the ability to transfer a specific collateral asset.\n     * @param assetIndex The index of the collateral asset to pause/unpause.\n     * @param paused Whether to pause (`true`) or unpause (`false`) transfer actions for the specified collateral asset.\n     */\n    function pauseCollateralAssetTransfer(uint24 assetIndex, bool paused) virtual external;\n    /**\n     * @notice Deactivates a collateral asset.\n     * @param assetIndex The index of the collateral asset to deactivate.\n     */\n    function deactivateCollateral(uint24 assetIndex) virtual external;\n    /**\n     * @notice Activates a collateral asset.\n     * @param assetIndex The index of the collateral asset to activate.\n     */\n    function activateCollateral(uint24 assetIndex) virtual external;\n\n    function collateralBalanceOf(address account, address asset) virtual external view returns (uint128);\n    function baseTrackingAccrued(address account) virtual external view returns (uint64);\n\n    function baseAccrualScale() virtual external view returns (uint64);\n    function baseIndexScale() virtual external view returns (uint64);\n    function factorScale() virtual external view returns (uint64);\n    function priceScale() virtual external view returns (uint64);\n\n    function maxAssets() virtual external view returns (uint8);\n\n    function totalsBasic() virtual external view returns (TotalsBasic memory);\n\n    function version() virtual external view returns (string memory);\n\n    /**\n      * ===== ERC20 interfaces =====\n      * Does not include the following functions/events, which are defined in `CometMainInterface` instead:\n      * - function decimals() virtual external view returns (uint8)\n      * - function totalSupply() virtual external view returns (uint256)\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      * - function balanceOf(address owner) virtual external view returns (uint256)\n      * - event Transfer(address indexed from, address indexed to, uint256 amount)\n      */\n    function name() virtual external view returns (string memory);\n    function symbol() virtual external view returns (string memory);\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      * @return Whether or not the approval succeeded\n      */\n    function approve(address spender, uint256 amount) virtual external returns (bool);\n\n    /**\n      * @notice Get the current allowance from `owner` for `spender`\n      * @param owner The address of the account which owns the tokens to be spent\n      * @param spender The address of the account which may transfer tokens\n      * @return The number of tokens allowed to be spent (-1 means infinite)\n      */\n    function allowance(address owner, address spender) virtual external view returns (uint256);\n\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n    /**\n     * @notice Emitted when the pause status for lenders' withdrawals is changed\n     * @param lendersWithdrawPaused Whether lenders' withdrawals are now paused\n     */\n    event LendersWithdrawPauseAction(bool lendersWithdrawPaused);\n    /**\n     * @notice Emitted when the pause status for borrowers' withdrawals is changed\n     * @param borrowersWithdrawPaused Whether borrowers' withdrawals are now paused\n     */\n    event BorrowersWithdrawPauseAction(bool borrowersWithdrawPaused);\n    /**\n     * @notice Emitted when the pause status for collateral withdrawals is changed\n     * @param collateralWithdrawPaused Whether collateral withdrawals are now paused\n     */\n    event CollateralWithdrawPauseAction(bool collateralWithdrawPaused);\n    /**\n     * @notice Emitted when the pause status for a specific collateral asset's withdrawals is changed\n     * @param assetIndex The index of the collateral asset\n     * @param collateralAssetWithdrawPaused Whether withdrawals for this collateral asset are now paused\n     */\n    event CollateralAssetWithdrawPauseAction(uint24 assetIndex, bool collateralAssetWithdrawPaused);\n    /**\n     * @notice Emitted when the pause status for collateral supply is changed\n     * @param collateralSupplyPaused Whether collateral supply is now paused\n     */\n    event CollateralSupplyPauseAction(bool collateralSupplyPaused);\n    /**\n     * @notice Emitted when the pause status for a specific collateral asset's supply is changed\n     * @param assetIndex The index of the collateral asset\n     * @param collateralAssetSupplyPaused Whether supply for this collateral asset is now paused\n     */\n    event CollateralAssetSupplyPauseAction(uint24 assetIndex, bool collateralAssetSupplyPaused);\n    /**\n     * @notice Emitted when the pause status for base supply is changed\n     * @param baseSupplyPaused Whether base supply is now paused\n     */\n    event BaseSupplyPauseAction(bool baseSupplyPaused);\n    /**\n     * @notice Emitted when the pause status for lenders' transfers is changed\n     * @param lendersTransferPaused Whether lenders' transfers are now paused\n     */\n    event LendersTransferPauseAction(bool lendersTransferPaused);\n    /**\n     * @notice Emitted when the pause status for borrowers' transfers is changed\n     * @param borrowersTransferPaused Whether borrowers' transfers are now paused\n     */\n    event BorrowersTransferPauseAction(bool borrowersTransferPaused);\n    /**\n     * @notice Emitted when the pause status for collateral transfers is changed\n     * @param collateralTransferPaused Whether collateral transfers are now paused\n     */\n    event CollateralTransferPauseAction(bool collateralTransferPaused);\n    /**\n     * @notice Emitted when the pause status for a specific collateral asset's transfers is changed\n     * @param assetIndex The index of the collateral asset\n     * @param collateralAssetTransferPaused Whether transfers for this collateral asset are now paused\n     */\n    event CollateralAssetTransferPauseAction(uint24 assetIndex, bool collateralAssetTransferPaused);\n    /**\n     * @notice Emitted when a collateral asset is deactivated\n     * @param assetIndex The index of the collateral asset that was deactivated\n     */\n    event CollateralDeactivated(uint24 assetIndex);\n    /**\n     * @notice Emitted when a collateral asset is activated\n     * @param assetIndex The index of the collateral asset that was activated\n     */\n    event CollateralActivated(uint24 assetIndex);\n}"},{"file_path":"contracts/CometExt.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometExtInterface.sol\";\nimport \"./CometMainInterface.sol\";\n\ncontract CometExt is CometExtInterface {\n    /** Public constants **/\n\n    /// @notice The major version of this contract\n    string public override constant version = \"0\";\n\n    /** Internal constants **/\n\n    /// @dev The EIP-712 typehash for the contract's domain\n    bytes32 internal constant DOMAIN_TYPEHASH = keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\");\n\n    /// @dev The EIP-712 typehash for allowBySig Authorization\n    bytes32 internal constant AUTHORIZATION_TYPEHASH = keccak256(\"Authorization(address owner,address manager,bool isAllowed,uint256 nonce,uint256 expiry)\");\n\n    /// @dev The highest valid value for s in an ECDSA signature pair (0 < s < secp256k1n ÷ 2 + 1)\n    ///  See https://ethereum.github.io/yellowpaper/paper.pdf #307)\n    uint internal constant MAX_VALID_ECDSA_S = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;\n\n    /** Immutable symbol **/\n\n    /// @dev The ERC20 name for wrapped base token\n    bytes32 internal immutable name32;\n\n    /// @dev The ERC20 symbol for wrapped base token\n    bytes32 internal immutable symbol32;\n\n    /** Modifiers **/\n\n    /**\n     * @dev Modifier to check if the sender is the governor or pause guardian\n     */\n    modifier onlyGovernorOrPauseGuardian() {\n        if (msg.sender != CometMainInterface(address(this)).governor() && \n        msg.sender != CometMainInterface(address(this)).pauseGuardian()) \n            revert OnlyPauseGuardianOrGovernor();\n        _;\n    }\n\n    /**\n     * @dev Modifier to check if the asset index is valid\n     * @param assetIndex The index of the asset\n     */\n    modifier isValidAssetIndex(uint24 assetIndex) {\n        if (assetIndex >= CometMainInterface(address(this)).numAssets()) revert InvalidAssetIndex();\n        _;\n    }\n\n    /**\n     * @notice Construct a new protocol instance\n     * @param config The mapping of initial/constant parameters\n     **/\n    constructor(ExtConfiguration memory config) {\n        name32 = config.name32;\n        symbol32 = config.symbol32;\n    }\n\n    /** External getters for internal constants **/\n\n    function baseAccrualScale() override external pure returns (uint64) { return BASE_ACCRUAL_SCALE; }\n    function baseIndexScale() override external pure returns (uint64) { return BASE_INDEX_SCALE; }\n    function factorScale() override external pure returns (uint64) { return FACTOR_SCALE; }\n    function priceScale() override external pure returns (uint64) { return PRICE_SCALE; }\n    function maxAssets() override virtual external pure returns (uint8) { return MAX_ASSETS; }\n\n    /**\n     * @notice Aggregate variables tracked for the entire market\n     **/\n    function totalsBasic() public override view returns (TotalsBasic memory) {\n        return TotalsBasic({\n            baseSupplyIndex: baseSupplyIndex,\n            baseBorrowIndex: baseBorrowIndex,\n            trackingSupplyIndex: trackingSupplyIndex,\n            trackingBorrowIndex: trackingBorrowIndex,\n            totalSupplyBase: totalSupplyBase,\n            totalBorrowBase: totalBorrowBase,\n            lastAccrualTime: lastAccrualTime,\n            pauseFlags: pauseFlags\n        });\n    }\n\n    /** Additional ERC20 functionality and approval interface **/\n\n    /**\n     * @notice Get the ERC20 name for wrapped base token\n     * @return The name as a string\n     */\n    function name() override public view returns (string memory) {\n        uint8 i;\n        for (i = 0; i < 32; ) {\n            if (name32[i] == 0) {\n                break;\n            }\n            unchecked { i++; }\n        }\n        bytes memory name_ = new bytes(i);\n        for (uint8 j = 0; j < i; ) {\n            name_[j] = name32[j];\n            unchecked { j++; }\n        }\n        return string(name_);\n    }\n\n    /**\n     * @notice Get the ERC20 symbol for wrapped base token\n     * @return The symbol as a string\n     */\n    function symbol() override external view returns (string memory) {\n        uint8 i;\n        for (i = 0; i < 32; ) {\n            if (symbol32[i] == 0) {\n                break;\n            }\n            unchecked { i++; }\n        }\n        bytes memory symbol_ = new bytes(i);\n        for (uint8 j = 0; j < i; ) {\n            symbol_[j] = symbol32[j];\n            unchecked { j++; }\n        }\n        return string(symbol_);\n    }\n\n    /**\n     * @notice Query the current collateral balance of an account\n     * @param account The account whose balance to query\n     * @param asset The collateral asset to check the balance for\n     * @return The collateral balance of the account\n     */\n    function collateralBalanceOf(address account, address asset) override external view returns (uint128) {\n        return userCollateral[account][asset].balance;\n    }\n\n    /**\n     * @notice Query the total accrued base rewards for an account\n     * @param account The account to query\n     * @return The accrued rewards, scaled by `BASE_ACCRUAL_SCALE`\n     */\n    function baseTrackingAccrued(address account) override external view returns (uint64) {\n        return userBasic[account].baseTrackingAccrued;\n    }\n\n    /**\n      * @notice Approve or disallow `spender` to transfer on sender's behalf\n      * @dev Note: this binary approval is unlike most other ERC20 tokens\n      * @dev Note: this grants full approval for spender to manage *all* the owner's assets\n      * @param spender The address of the account which may transfer tokens\n      * @param amount Either uint.max (to allow) or zero (to disallow)\n      * @return Whether or not the approval change succeeded\n      */\n    function approve(address spender, uint256 amount) override external returns (bool) {\n        if (amount == type(uint256).max) {\n            allowInternal(msg.sender, spender, true);\n        } else if (amount == 0) {\n            allowInternal(msg.sender, spender, false);\n        } else {\n            revert BadAmount();\n        }\n        return true;\n    }\n\n    /**\n      * @notice Get the current allowance from `owner` for `spender`\n      * @dev Note: this binary allowance is unlike most other ERC20 tokens\n      * @dev Note: this allowance allows spender to manage *all* the owner's assets\n      * @param owner The address of the account which owns the tokens to be spent\n      * @param spender The address of the account which may transfer tokens\n      * @return Either uint.max (spender is allowed) or zero (spender is disallowed)\n      */\n    function allowance(address owner, address spender) override external view returns (uint256) {\n        return hasPermission(owner, spender) ? type(uint256).max : 0;\n    }\n\n    /**\n     * @notice Allow or disallow another address to withdraw, or transfer from the sender\n     * @param manager The account which will be allowed or disallowed\n     * @param isAllowed_ Whether to allow or disallow\n     */\n    function allow(address manager, bool isAllowed_) override external {\n        allowInternal(msg.sender, manager, isAllowed_);\n    }\n\n    /**\n     * @dev Stores the flag marking whether the manager is allowed to act on behalf of owner\n     */\n    function allowInternal(address owner, address manager, bool isAllowed_) internal {\n        isAllowed[owner][manager] = isAllowed_;\n        emit Approval(owner, manager, isAllowed_ ? type(uint256).max : 0);\n    }\n\n    /**\n     * @notice Sets authorization status for a manager via signature from signatory\n     * @param owner The address that signed the signature\n     * @param manager The address to authorize (or rescind authorization from)\n     * @param isAllowed_ Whether to authorize or rescind authorization from manager\n     * @param nonce The next expected nonce value for the signatory\n     * @param expiry Expiration time for the signature\n     * @param v The recovery byte of the signature\n     * @param r Half of the ECDSA signature pair\n     * @param s Half of the ECDSA signature pair\n     */\n    function allowBySig(\n        address owner,\n        address manager,\n        bool isAllowed_,\n        uint256 nonce,\n        uint256 expiry,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) override external {\n        if (uint256(s) > MAX_VALID_ECDSA_S) revert InvalidValueS();\n        // v ∈ {27, 28} (source: https://ethereum.github.io/yellowpaper/paper.pdf #308)\n        if (v != 27 && v != 28) revert InvalidValueV();\n        bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), keccak256(bytes(version)), block.chainid, address(this)));\n        bytes32 structHash = keccak256(abi.encode(AUTHORIZATION_TYPEHASH, owner, manager, isAllowed_, nonce, expiry));\n        bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n        address signatory = ecrecover(digest, v, r, s);\n        if (signatory == address(0)) revert BadSignatory();\n        if (owner != signatory) revert BadSignatory();\n        if (nonce != userNonce[signatory]++) revert BadNonce();\n        if (block.timestamp >= expiry) revert SignatureExpired();\n        allowInternal(signatory, manager, isAllowed_);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        EXTENDED PAUSE CONTROL\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Set the status of a pause offset\n     * @param offset The offset to set\n     * @param paused The new status of the pause offset\n     */\n    function setPauseFlag(uint24 offset, bool paused) internal {\n        paused ? extendedPauseFlags |= (uint24(1) << offset) : extendedPauseFlags &= ~(uint24(1) << offset);\n    }\n\n    /**\n     * @notice Get the current status of a pause offset\n     * @param offset The offset to check\n     * @return The current status of the pause offset\n     */\n    function currentPauseOffsetStatus(uint24 offset) internal view returns (bool) {\n        return (extendedPauseFlags & (uint24(1) << offset)) != 0;\n    }\n\n    /**\n     * @notice Check if the collateral asset is deactivated\n     * @param assetIndex The index of the collateral asset\n     * @return Whether the collateral asset is deactivated\n     */\n    function isCollateralDeactivated(uint24 assetIndex) public view returns (bool) {\n        return (deactivatedCollaterals & (uint24(1) << assetIndex) != 0) == true;\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseLendersWithdraw(bool paused) override external onlyGovernorOrPauseGuardian {\n        if (currentPauseOffsetStatus(PAUSE_LENDERS_WITHDRAW_OFFSET) == paused) revert OffsetStatusAlreadySet(PAUSE_LENDERS_WITHDRAW_OFFSET, paused);\n\n        setPauseFlag(PAUSE_LENDERS_WITHDRAW_OFFSET, paused);\n\n        emit LendersWithdrawPauseAction(paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseBorrowersWithdraw(bool paused) override external onlyGovernorOrPauseGuardian {\n        if (currentPauseOffsetStatus(PAUSE_BORROWERS_WITHDRAW_OFFSET) == paused) revert OffsetStatusAlreadySet(PAUSE_BORROWERS_WITHDRAW_OFFSET, paused);\n\n        setPauseFlag(PAUSE_BORROWERS_WITHDRAW_OFFSET, paused);\n\n        emit BorrowersWithdrawPauseAction(paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseCollateralWithdraw(bool paused) override external onlyGovernorOrPauseGuardian {\n        if (currentPauseOffsetStatus(PAUSE_COLLATERALS_WITHDRAW_OFFSET) == paused) revert OffsetStatusAlreadySet(PAUSE_COLLATERALS_WITHDRAW_OFFSET, paused);\n\n        setPauseFlag(PAUSE_COLLATERALS_WITHDRAW_OFFSET, paused);\n\n        emit CollateralWithdrawPauseAction(paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseCollateralAssetWithdraw(uint24 assetIndex, bool paused) override external onlyGovernorOrPauseGuardian isValidAssetIndex(assetIndex) {\n        if ((collateralsWithdrawPauseFlags & (uint24(1) << assetIndex) != 0) == paused) revert CollateralAssetOffsetStatusAlreadySet(collateralsWithdrawPauseFlags, assetIndex, paused);\n\n        paused ? collateralsWithdrawPauseFlags |= (uint24(1) << assetIndex) : collateralsWithdrawPauseFlags &= ~(uint24(1) << assetIndex);\n\n        emit CollateralAssetWithdrawPauseAction(assetIndex, paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseCollateralSupply(bool paused) override external onlyGovernorOrPauseGuardian {\n        if (currentPauseOffsetStatus(PAUSE_COLLATERAL_SUPPLY_OFFSET) == paused) revert OffsetStatusAlreadySet(PAUSE_COLLATERAL_SUPPLY_OFFSET, paused);\n\n        setPauseFlag(PAUSE_COLLATERAL_SUPPLY_OFFSET, paused);\n        \n        emit CollateralSupplyPauseAction(paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseBaseSupply(bool paused) override external onlyGovernorOrPauseGuardian {\n        if (currentPauseOffsetStatus(PAUSE_BASE_SUPPLY_OFFSET) == paused) revert OffsetStatusAlreadySet(PAUSE_BASE_SUPPLY_OFFSET, paused);\n\n        setPauseFlag(PAUSE_BASE_SUPPLY_OFFSET, paused);\n\n        emit BaseSupplyPauseAction(paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseCollateralAssetSupply(uint24 assetIndex, bool paused) override external onlyGovernorOrPauseGuardian isValidAssetIndex(assetIndex) {\n        if ((collateralsSupplyPauseFlags & (uint24(1) << assetIndex) != 0) == paused) revert CollateralAssetOffsetStatusAlreadySet(collateralsSupplyPauseFlags, assetIndex, paused);\n        if (!paused && isCollateralDeactivated(assetIndex)) revert CollateralIsDeactivated(assetIndex);\n\n        paused ? collateralsSupplyPauseFlags |= (uint24(1) << assetIndex) : collateralsSupplyPauseFlags &= ~(uint24(1) << assetIndex);\n\n        emit CollateralAssetSupplyPauseAction(assetIndex, paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseLendersTransfer(bool paused) override external onlyGovernorOrPauseGuardian {\n        if (currentPauseOffsetStatus(PAUSE_LENDERS_TRANSFER_OFFSET) == paused) revert OffsetStatusAlreadySet(PAUSE_LENDERS_TRANSFER_OFFSET, paused);\n\n        setPauseFlag(PAUSE_LENDERS_TRANSFER_OFFSET, paused);\n\n        emit LendersTransferPauseAction(paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseBorrowersTransfer(bool paused) override external onlyGovernorOrPauseGuardian {\n        if (currentPauseOffsetStatus(PAUSE_BORROWERS_TRANSFER_OFFSET) == paused) revert OffsetStatusAlreadySet(PAUSE_BORROWERS_TRANSFER_OFFSET, paused);\n\n        setPauseFlag(PAUSE_BORROWERS_TRANSFER_OFFSET, paused);\n\n        emit BorrowersTransferPauseAction(paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseCollateralTransfer(bool paused) override external onlyGovernorOrPauseGuardian {\n        if (currentPauseOffsetStatus(PAUSE_COLLATERALS_TRANSFER_OFFSET) == paused) revert OffsetStatusAlreadySet(PAUSE_COLLATERALS_TRANSFER_OFFSET, paused);\n\n        setPauseFlag(PAUSE_COLLATERALS_TRANSFER_OFFSET, paused);\n\n        emit CollateralTransferPauseAction(paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function pauseCollateralAssetTransfer(uint24 assetIndex, bool paused) override external onlyGovernorOrPauseGuardian isValidAssetIndex(assetIndex) {\n        if ((collateralsTransferPauseFlags & (uint24(1) << assetIndex) != 0) == paused) revert CollateralAssetOffsetStatusAlreadySet(collateralsTransferPauseFlags, assetIndex, paused);\n        if (!paused && isCollateralDeactivated(assetIndex)) revert CollateralIsDeactivated(assetIndex);\n\n        paused ? collateralsTransferPauseFlags |= (uint24(1) << assetIndex) : collateralsTransferPauseFlags &= ~(uint24(1) << assetIndex);\n\n        emit CollateralAssetTransferPauseAction(assetIndex, paused);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function deactivateCollateral(uint24 assetIndex) override external isValidAssetIndex(assetIndex) {\n        if (msg.sender != CometMainInterface(address(this)).pauseGuardian()) revert OnlyPauseGuardian();\n        if (isCollateralDeactivated(assetIndex)) revert CollateralIsDeactivated(assetIndex);\n\n        // Mark collateral as deactivated\n        deactivatedCollaterals |= (uint24(1) << assetIndex);\n        emit CollateralDeactivated(assetIndex);\n        \n        // Pause supply of this collateral\n        collateralsSupplyPauseFlags |= (uint24(1) << assetIndex);\n        emit CollateralAssetSupplyPauseAction(assetIndex, true);\n        \n        // Pause transfer of this collateral\n        collateralsTransferPauseFlags |= (uint24(1) << assetIndex);\n        emit CollateralAssetTransferPauseAction(assetIndex, true);\n    }\n\n    /**\n     * @inheritdoc CometExtInterface\n     */\n    function activateCollateral(uint24 assetIndex) override external isValidAssetIndex(assetIndex) {\n        if (msg.sender != CometMainInterface(address(this)).governor()) revert OnlyGovernor();\n        if ((deactivatedCollaterals & (uint24(1) << assetIndex) != 0) == false) revert CollateralIsActivated(assetIndex);\n\n        // Mark collateral as activated\n        deactivatedCollaterals &= ~(uint24(1) << assetIndex);\n        emit CollateralActivated(assetIndex);\n        \n        // Unpause supply of this collateral\n        collateralsSupplyPauseFlags &= ~(uint24(1) << assetIndex);\n        emit CollateralAssetSupplyPauseAction(assetIndex, false);\n\n        // Unpause transfer of this collateral\n        collateralsTransferPauseFlags &= ~(uint24(1) << assetIndex);\n        emit CollateralAssetTransferPauseAction(assetIndex, false);\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-periphery/contracts/interfaces/external/IWETH9.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.15;\n\nimport '../../../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\n/// @title Interface for WETH9\ninterface IWETH9 is IERC20 {\n    /// @notice Deposit ether to get wrapped ether\n    function deposit() external payable;\n\n    /// @notice Withdraw wrapped ether to get ether\n    function withdraw(uint256) external;\n}\n"},{"file_path":"contracts/test/Dog.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\ncontract Dog {\n    bool public initialized;\n    string public name;\n    Dog public father;\n    Dog[] public pups;\n\n    struct Puppers {\n        uint index;\n        Dog pup;\n    }\n\n    function initializeDog(string memory name_, Dog father_, Dog[] memory pups_) public {\n        require(!initialized, \"already initialized\");\n        initialized = true;\n        name = name_;\n        father = father_;\n        for (uint i = 0; i < pups_.length; i++) {\n            pups.push(pups_[i]);\n        }\n    }\n\n    constructor(string memory name_, Dog father_, Dog[] memory pups_) {\n        initializeDog(name_, father_, pups_);\n    }\n\n    function addPup(Dog pup) public {\n        pups.push(pup);\n    }\n\n    function puppers() public returns (Puppers[] memory) {\n        Puppers[] memory puppers = new Puppers[](pups.length);\n        for (uint i = 0; i < pups.length; i++) {\n            puppers[i] = Puppers({\n                index: i,\n                pup: pups[i]\n            });\n        }\n        return puppers;\n    }\n}\n"},{"file_path":"contracts/vendor/Timelock.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../ITimelock.sol\";\n\ncontract Timelock is ITimelock {\n    uint public immutable GRACE_PERIOD;\n    uint public immutable MINIMUM_DELAY;\n    uint public immutable MAXIMUM_DELAY;\n\n    address public admin;\n    address public pendingAdmin;\n    uint public delay;\n\n    mapping (bytes32 => bool) public queuedTransactions;\n\n    constructor(address admin_, uint delay_, uint gracePeriod_, uint minimumDelay_, uint maxiumumDelay_) public {\n        require(delay_ >= minimumDelay_, \"Timelock::constructor: Delay must exceed minimum delay.\");\n        require(delay_ <= maxiumumDelay_, \"Timelock::setDelay: Delay must not exceed maximum delay.\");\n\n        GRACE_PERIOD = gracePeriod_;\n        MINIMUM_DELAY = minimumDelay_;\n        MAXIMUM_DELAY = maxiumumDelay_;\n\n        admin = admin_;\n        delay = delay_;\n    }\n\n    fallback() external payable { }\n\n    function setDelay(uint delay_) public {\n        require(msg.sender == address(this), \"Timelock::setDelay: Call must come from Timelock.\");\n        require(delay_ >= MINIMUM_DELAY, \"Timelock::setDelay: Delay must exceed minimum delay.\");\n        require(delay_ <= MAXIMUM_DELAY, \"Timelock::setDelay: Delay must not exceed maximum delay.\");\n        delay = delay_;\n\n        emit NewDelay(delay);\n    }\n\n    function acceptAdmin() public {\n        require(msg.sender == pendingAdmin, \"Timelock::acceptAdmin: Call must come from pendingAdmin.\");\n        admin = msg.sender;\n        pendingAdmin = address(0);\n\n        emit NewAdmin(admin);\n    }\n\n    function setPendingAdmin(address pendingAdmin_) public {\n        require(msg.sender == address(this), \"Timelock::setPendingAdmin: Call must come from Timelock.\");\n        pendingAdmin = pendingAdmin_;\n\n        emit NewPendingAdmin(pendingAdmin);\n    }\n\n    function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {\n        require(msg.sender == admin, \"Timelock::queueTransaction: Call must come from admin.\");\n        require(eta >= (getBlockTimestamp() + delay), \"Timelock::queueTransaction: Estimated execution block must satisfy delay.\");\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        queuedTransactions[txHash] = true;\n\n        emit QueueTransaction(txHash, target, value, signature, data, eta);\n        return txHash;\n    }\n\n    function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public {\n        require(msg.sender == admin, \"Timelock::cancelTransaction: Call must come from admin.\");\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        queuedTransactions[txHash] = false;\n\n        emit CancelTransaction(txHash, target, value, signature, data, eta);\n    }\n\n    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {\n        require(msg.sender == admin, \"Timelock::executeTransaction: Call must come from admin.\");\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        require(queuedTransactions[txHash], \"Timelock::executeTransaction: Transaction hasn't been queued.\");\n        require(getBlockTimestamp() >= eta, \"Timelock::executeTransaction: Transaction hasn't surpassed time lock.\");\n        require(getBlockTimestamp() <= (eta + GRACE_PERIOD), \"Timelock::executeTransaction: Transaction is stale.\");\n\n        queuedTransactions[txHash] = false;\n\n        bytes memory callData;\n\n        if (bytes(signature).length == 0) {\n            callData = data;\n        } else {\n            callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);\n        }\n\n        (bool success, bytes memory returnData) = target.call{value: value}(callData);\n        require(success, \"Timelock::executeTransaction: Transaction execution reverted.\");\n\n        emit ExecuteTransaction(txHash, target, value, signature, data, eta);\n\n        return returnData;\n    }\n\n    function getBlockTimestamp() internal view returns (uint) {\n        return block.timestamp;\n    }\n}\n"},{"file_path":"contracts/bridges/SweepableBridgeReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../IERC20NonStandard.sol\";\nimport \"./BaseBridgeReceiver.sol\";\n\ncontract SweepableBridgeReceiver is BaseBridgeReceiver {\n    error FailedToSendNativeToken();\n    error TransferOutFailed();\n\n    /**\n     * @notice A public function to sweep accidental ERC-20 transfers to this contract\n     * @dev Note: Make sure to check that the asset being swept out is not malicious\n     * @param recipient The address that will receive the swept funds\n     * @param asset The address of the ERC-20 token to sweep\n     */\n    function sweepToken(address recipient, address asset) external {\n        if (msg.sender != localTimelock) revert Unauthorized();\n\n        uint256 balance = IERC20NonStandard(asset).balanceOf(address(this));\n        doTransferOut(asset, recipient, balance);\n    }\n\n    /**\n     * @notice A public function to sweep accidental native token transfers to this contract\n     * @param recipient The address that will receive the swept funds\n     */\n    function sweepNativeToken(address recipient) external {\n        if (msg.sender != localTimelock) revert Unauthorized();\n\n        uint256 balance = address(this).balance;\n        (bool success, ) = recipient.call{ value: balance }(\"\");\n        if (!success) revert FailedToSendNativeToken();\n    }\n\n    /**\n     * @notice Similar to ERC-20 transfer, except it properly handles `transfer` from non-standard ERC-20 tokens\n     * @param asset The ERC-20 token to transfer out\n     * @param to The recipient of the token transfer\n     * @param amount The amount of the token to transfer\n     * @dev Note: This wrapper 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\n        bool success;\n        assembly {\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}"},{"file_path":"contracts/vendor/proxy/beacon/IBeacon.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {BeaconProxy} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"},{"file_path":"contracts/pricefeeds/ScalingPriceFeedWithCustomDescription.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title Scaling price feed\n * @notice A custom price feed that scales up or down the price received from an underlying price feed and returns the result\n * @author Compound\n */\ncontract ScalingPriceFeedWithCustomDescription is IPriceFeed {\n    /** Custom errors **/\n    error InvalidInt256();\n\n    /// @notice Version of the price feed\n    uint public constant override version = 1;\n\n    /// @notice Description of the price feed\n    string public description;\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Underlying price feed where prices are fetched from\n    address public immutable underlyingPriceFeed;\n\n    /// @notice Whether or not the price should be upscaled\n    bool internal immutable shouldUpscale;\n\n    /// @notice The amount to upscale or downscale the price by\n    int256 internal immutable rescaleFactor;\n\n    /**\n     * @notice Construct a new scaling price feed\n     * @param underlyingPriceFeed_ The address of the underlying price feed to fetch prices from\n     * @param decimals_ The number of decimals for the returned prices\n     **/\n    constructor(address underlyingPriceFeed_, uint8 decimals_, string memory description_) {\n        underlyingPriceFeed = underlyingPriceFeed_;\n        decimals = decimals_;\n        description = description_;\n\n        uint8 underlyingPriceFeedDecimals = AggregatorV3Interface(underlyingPriceFeed_).decimals();\n        // Note: Solidity does not allow setting immutables in if/else statements\n        shouldUpscale = underlyingPriceFeedDecimals < decimals_ ? true : false;\n        rescaleFactor = (shouldUpscale\n            ? signed256(10 ** (decimals_ - underlyingPriceFeedDecimals))\n            : signed256(10 ** (underlyingPriceFeedDecimals - decimals_))\n        );\n    }\n\n    /**\n     * @notice Price for the latest round\n     * @return roundId Round id from the underlying price feed\n     * @return answer Latest price for the asset in terms of ETH\n     * @return startedAt Timestamp when the round was started; passed on from underlying price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from underlying price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed\n     **/\n    function latestRoundData() override external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        (uint80 roundId_, int256 price, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(underlyingPriceFeed).latestRoundData();\n        return (roundId_, scalePrice(price), startedAt_, updatedAt_, answeredInRound_);\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 scalePrice(int256 price) internal view returns (int256) {\n        int256 scaledPrice;\n        if (shouldUpscale) {\n            scaledPrice = price * rescaleFactor;\n        } else {\n            scaledPrice = price / rescaleFactor;\n        }\n        return scaledPrice;\n    }\n}"},{"file_path":"contracts/bridges/test/SweepableBridgeReceiverHarness.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../SweepableBridgeReceiver.sol\";\n\ncontract SweepableBridgeReceiverHarness is SweepableBridgeReceiver {\n    function processMessageExternal(\n        address rootMessageSender,\n        bytes calldata data\n    ) external {\n        processMessage(rootMessageSender, data);\n    }\n\n    fallback() external payable { }\n}\n"},{"file_path":"contracts/bridges/BaseBridgeReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../ITimelock.sol\";\n\ncontract BaseBridgeReceiver {\n    /** Custom errors **/\n    error AlreadyInitialized();\n    error BadData();\n    error InvalidProposalId();\n    error InvalidTimelockAdmin();\n    error ProposalNotExecutable();\n    error TransactionAlreadyQueued();\n    error Unauthorized();\n\n    /** Events **/\n    event Initialized(address indexed govTimelock, address indexed localTimelock);\n    event ProposalCreated(address indexed rootMessageSender, uint id, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint eta);\n    event ProposalExecuted(uint indexed id);\n\n    /** Public variables **/\n\n    /// @notice Address of the governing contract that this bridge receiver expects to\n    ///  receive messages from; likely an address from another chain (e.g. mainnet)\n    address public govTimelock;\n\n    /// @notice Address of the timelock on this chain that the bridge receiver\n    /// will send messages to\n    address public localTimelock;\n\n    /// @notice Whether contract has been initialized\n    bool public initialized;\n\n    /// @notice Total count of proposals generated\n    uint public proposalCount;\n\n    struct Proposal {\n        uint id;\n        address[] targets;\n        uint[] values;\n        string[] signatures;\n        bytes[] calldatas;\n        uint eta;\n        bool executed;\n    }\n\n    /// @notice Mapping of proposal ids to their full proposal data\n    mapping (uint => Proposal) public proposals;\n\n    enum ProposalState {\n        Queued,\n        Expired,\n        Executed\n    }\n\n    /**\n     * @notice Initialize the contract\n     * @param _govTimelock Address of the governing contract that this contract\n     * will receive messages from (likely on another chain)\n     * @param _localTimelock Address of the timelock contract that this contract\n     * will send messages to\n     */\n    function initialize(address _govTimelock, address _localTimelock) external {\n        if (initialized) revert AlreadyInitialized();\n        if (ITimelock(_localTimelock).admin() != address(this)) revert InvalidTimelockAdmin();\n        govTimelock = _govTimelock;\n        localTimelock = _localTimelock;\n        initialized = true;\n        emit Initialized(_govTimelock, _localTimelock);\n    }\n\n    /**\n     * @notice Process a message sent from the governing timelock (across a bridge)\n     * @param rootMessageSender Address of the contract that sent the bridged message\n     * @param data ABI-encoded bytes containing the transactions to be queued on the local timelock\n     */\n    function processMessage(\n        address rootMessageSender,\n        bytes calldata data\n    ) internal {\n        if (rootMessageSender != govTimelock) revert Unauthorized();\n\n        address[] memory targets;\n        uint256[] memory values;\n        string[] memory signatures;\n        bytes[] memory calldatas;\n\n        (targets, values, signatures, calldatas) = abi.decode(\n            data,\n            (address[], uint256[], string[], bytes[])\n        );\n\n        if (values.length != targets.length) revert BadData();\n        if (signatures.length != targets.length) revert BadData();\n        if (calldatas.length != targets.length) revert BadData();\n\n        uint delay = ITimelock(localTimelock).delay();\n        uint eta = block.timestamp + delay;\n\n        for (uint i = 0; i < targets.length; i++) {\n            if (ITimelock(localTimelock).queuedTransactions(keccak256(abi.encode(targets[i], values[i], signatures[i], calldatas[i], eta)))) revert TransactionAlreadyQueued();\n            ITimelock(localTimelock).queueTransaction(targets[i], values[i], signatures[i], calldatas[i], eta);\n        }\n\n        proposalCount++;\n        Proposal memory proposal = Proposal({\n            id: proposalCount,\n            targets: targets,\n            values: values,\n            signatures: signatures,\n            calldatas: calldatas,\n            eta: eta,\n            executed: false\n        });\n\n        proposals[proposal.id] = proposal;\n        emit ProposalCreated(rootMessageSender, proposal.id, targets, values, signatures, calldatas, eta);\n    }\n\n    /**\n     * @notice Execute a queued proposal\n     * @param proposalId The id of the proposal to execute\n     */\n    function executeProposal(uint proposalId) external {\n        if (state(proposalId) != ProposalState.Queued) revert ProposalNotExecutable();\n        Proposal storage proposal = proposals[proposalId];\n        proposal.executed = true;\n        for (uint i = 0; i < proposal.targets.length; i++) {\n            ITimelock(localTimelock).executeTransaction(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], proposal.eta);\n        }\n        emit ProposalExecuted(proposalId);\n    }\n\n    /**\n     * @notice Get the state of a proposal\n     * @param proposalId Id of the proposal\n     * @return The state of the given proposal (queued, expired or executed)\n     */\n    function state(uint proposalId) public view returns (ProposalState) {\n        if (proposalId > proposalCount || proposalId == 0) revert InvalidProposalId();\n        Proposal memory proposal = proposals[proposalId];\n        if (proposal.executed) {\n            return ProposalState.Executed;\n        } else if (block.timestamp > (proposal.eta + ITimelock(localTimelock).GRACE_PERIOD())) {\n            return ProposalState.Expired;\n        } else {\n            return ProposalState.Queued;\n        }\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-periphery/contracts/interfaces/IPeripheryPayments.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\n\n/// @title Periphery Payments\n/// @notice Functions to ease deposits and withdrawals of ETH\ninterface IPeripheryPayments {\n    /// @notice Unwraps the contract's WETH9 balance and sends it to recipient as ETH.\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing WETH9 from users.\n    /// @param amountMinimum The minimum amount of WETH9 to unwrap\n    /// @param recipient The address receiving ETH\n    function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;\n\n    /// @notice Refunds any ETH balance held by this contract to the `msg.sender`\n    /// @dev Useful for bundling with mint or increase liquidity that uses ether, or exact output swaps\n    /// that use ether for the input amount\n    function refundETH() external payable;\n\n    /// @notice Transfers the full amount of a token held by this contract to recipient\n    /// @dev The amountMinimum parameter prevents malicious contracts from stealing the token from users\n    /// @param token The contract address of the token which will be transferred to `recipient`\n    /// @param amountMinimum The minimum amount of token required for a transfer\n    /// @param recipient The destination address of the token\n    function sweepToken(\n        address token,\n        uint256 amountMinimum,\n        address recipient\n    ) external payable;\n}\n"},{"file_path":"contracts/vendor/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"},{"file_path":"contracts/ITimelock.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @dev Interface for interacting with a Timelock\n */\ninterface ITimelock {\n    /// @notice Event emitted when a pending admin accepts admin position\n    event NewAdmin(address indexed newAdmin);\n\n    /// @notice Event emitted when new pending admin is set by the timelock\n    event NewPendingAdmin(address indexed newPendingAdmin);\n\n    /// @notice Event emitted when Timelock sets new delay value\n    event NewDelay(uint indexed newDelay);\n\n    /// @notice Event emitted when admin cancels an enqueued transaction\n    event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\n\n    /// @notice Event emitted when admin executes an enqueued transaction\n    event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\n\n    /// @notice Event emitted when admin enqueues a transaction\n    event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\n\n    /// @notice The length of time, once the delay has passed, in which a transaction can be executed before it becomes stale\n    function GRACE_PERIOD() virtual external view returns (uint);\n\n    /// @notice The minimum value that the `delay` variable can be set to\n    function MINIMUM_DELAY() virtual external view returns (uint);\n\n    /// @notice The maximum value that the `delay` variable can be set to\n    function MAXIMUM_DELAY() virtual external view returns (uint);\n\n    /// @notice Address that has admin privileges\n    function admin() virtual external view returns (address);\n\n    /// @notice The address that may become the new admin by calling `acceptAdmin()`\n    function pendingAdmin() virtual external view returns (address);\n\n    /**\n     * @notice Set the pending admin\n     * @param pendingAdmin_ New pending admin address\n     */\n    function setPendingAdmin(address pendingAdmin_) virtual external;\n\n    /**\n     * @notice Accept the position of admin (if caller is the current pendingAdmin)\n     */\n    function acceptAdmin() virtual external;\n\n    /// @notice Duration that a transaction must be queued before it can be executed\n    function delay() virtual external view returns (uint);\n\n    /**\n     * @notice Set the delay value\n     * @param delay New delay value\n     */\n    function setDelay(uint delay) virtual external;\n\n    /// @notice Mapping of transaction hashes to whether that transaction is currently enqueued\n    function queuedTransactions(bytes32 txHash) virtual external returns (bool);\n\n    /**\n     * @notice Enque a transaction\n     * @param target Address that the transaction is targeted at\n     * @param value Value to send to target address\n     * @param signature Function signature to call on target address\n     * @param data Calldata for function called on target address\n     * @param eta Timestamp of when the transaction can be executed\n     * @return txHash of the enqueued transaction\n     */\n    function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) virtual external returns (bytes32);\n\n    /**\n     * @notice Cancel an enqueued transaction\n     * @param target Address that the transaction is targeted at\n     * @param value Value of the transaction to cancel\n     * @param signature Function signature of the transaction to cancel\n     * @param data Calldata for the transaction to cancel\n     * @param eta Timestamp of the transaction to cancel\n     */\n    function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) virtual external;\n\n    /**\n     * @notice Execute an enqueued transaction\n     * @param target Target address of the transaction to execute\n     * @param value Value of the transaction to execute\n     * @param signature Function signature of the transaction to execute\n     * @param data Calldata for the transaction to execute\n     * @param eta Timestamp of the transaction to execute\n     * @return bytes returned from executing transaction\n     */\n    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) virtual external payable returns (bytes memory);\n}\n"},{"file_path":"contracts/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.15;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}"},{"file_path":"contracts/CometFactoryWithExtendedAssetList.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometWithExtendedAssetList.sol\";\nimport \"./CometConfiguration.sol\";\n\ncontract CometFactoryWithExtendedAssetList is CometConfiguration {\n    function clone(Configuration calldata config) external returns (address) {\n        return address(new CometWithExtendedAssetList(config));\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport './pool/IUniswapV3PoolImmutables.sol';\nimport './pool/IUniswapV3PoolState.sol';\nimport './pool/IUniswapV3PoolDerivedState.sol';\nimport './pool/IUniswapV3PoolActions.sol';\nimport './pool/IUniswapV3PoolOwnerActions.sol';\nimport './pool/IUniswapV3PoolEvents.sol';\n\n/// @title The interface for a Uniswap V3 Pool\n/// @notice A Uniswap pool facilitates swapping and automated market making between any two assets that strictly conform\n/// to the ERC20 specification\n/// @dev The pool interface is broken up into many smaller pieces\ninterface IUniswapV3Pool is\n    IUniswapV3PoolImmutables,\n    IUniswapV3PoolState,\n    IUniswapV3PoolDerivedState,\n    IUniswapV3PoolActions,\n    IUniswapV3PoolOwnerActions,\n    IUniswapV3PoolEvents\n{\n\n}\n"},{"file_path":"contracts/liquidator/interfaces/IUniswapV2Router.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @dev Interface for interacting with Uniswap and SushiSwap Routers\n * Note Not a comprehensive interface\n */\ninterface IUniswapV2Router {\n    function swapExactTokensForTokens(\n        uint256 amountIn,\n        uint256 amountOutMin,\n        address[] calldata path,\n        address to,\n        uint256 deadline\n    ) external returns (uint256[] memory amounts);\n}"},{"file_path":"contracts/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.15;\n\nimport {IERC20} from \"./IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}"},{"file_path":"contracts/test/GovernorSimple.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\ninterface TimelockInterface {\n    function queuedTransactions(bytes32 hash) external view returns (bool);\n    function queueTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external returns (bytes32);\n    function cancelTransaction(address target, uint value, string calldata signature, bytes calldata data) external;\n    function executeTransaction(address target, uint value, string calldata signature, bytes calldata data, uint eta) external payable returns (bytes memory);\n    function executeTransactions(address[] calldata targets, uint[] calldata values, string[] calldata signatures, bytes[] calldata data) external payable;\n}\n\n/**\n  * GovSimple:\n  *  - A system similar to Compound's Governor{Alpha, Bravo, Charlie} but just for test-net.\n  *  - Instead of allowing voting by tokens, the system is run by a set of admins with unlimited power. Anyone in this set should be able to add or remove other admins (it's test-net).\n  *  - There is no voting - everything passes by will of any admin.\n  *  - The ABI for proposing, queueing, executing should be identical to main-net. The execution should, similarly, go through a simple test-net Timelock.\n  *  - ABI:\n  *    - function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public returns (uint)\n  *    - function queue(uint proposalId) public\n  *    - function execute(uint proposalId) public payable\n */\ncontract GovernorSimple {\n\n    /// @notice An event emitted when a new proposal is created\n    event ProposalCreated(uint id, address proposer, address[] targets, uint[] values, string[] signatures, bytes[] calldatas, uint startBlock, string description);\n\n    /// @notice An event emitted when a proposal has been canceled\n    event ProposalCanceled(uint id);\n\n    /// @notice An event emitted when a proposal has been queued in the Timelock\n    event ProposalQueued(uint id);\n\n    /// @notice An event emitted when a proposal has been executed in the Timelock\n    event ProposalExecuted(uint id);\n\n    /// @notice The maximum number of actions that can be included in a proposal\n    uint public constant proposalMaxOperations = 10; // 10 actions\n\n    /// @notice The timelock\n    TimelockInterface public timelock;\n\n    /// @notice The list of admins that can propose, cancel, queue, and execute proposals\n    address[] public admins;\n\n    /// @notice The total number of proposals\n    uint public proposalCount;\n\n    /// @notice The official record of all proposals ever proposed\n    mapping (uint => Proposal) public proposals;\n\n    struct Proposal {\n        /// @notice Unique id for looking up a proposal\n        uint id;\n\n        /// @notice Creator of the proposal\n        address proposer;\n\n        /// @notice the ordered list of target addresses for calls to be made\n        address[] targets;\n\n        /// @notice The ordered list of values (i.e. msg.value) to be passed to the calls to be made\n        uint[] values;\n\n        /// @notice The ordered list of function signatures to be called\n        string[] signatures;\n\n        /// @notice The ordered list of calldata to be passed to each call\n        bytes[] calldatas;\n\n        /// @notice The block at which voting begins: holders must delegate their votes prior to this block\n        uint startBlock;\n\n        /// @notice Flag marking whether the proposal has been canceled\n        bool canceled;\n\n        /// @notice Flag marking whether the proposal has been queued\n        bool queued;\n\n        /// @notice Flag marking whether the proposal has been executed\n        bool executed;\n    }\n\n    /// @notice Possible states that a proposal may be in\n    enum ProposalState {\n        Active,\n        Canceled,\n        Queued,\n        Executed\n    }\n\n    /**\n      * @notice Initialize the initial contract storage\n      * @param timelock_ The address of the Timelock\n      * @param admins_ The admins of governor\n      */\n    function initialize(address timelock_, address[] memory admins_) external {\n        require(address(timelock) == address(0), \"GovernorSimple::initialize: can only initialize once\");\n        timelock = TimelockInterface(timelock_);\n        admins = admins_;\n    }\n\n    /**\n      * @notice Function used to propose a new proposal. Sender must be a governor\n      * @param targets Target addresses for proposal calls\n      * @param values Eth values for proposal calls\n      * @param signatures Function signatures for proposal calls\n      * @param calldatas Calldatas for proposal calls\n      * @param description String description of the proposal\n      * @return Proposal id of new proposal\n      */\n    function propose(address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description) public returns (uint) {\n        require(isAdmin(msg.sender), \"GovernorSimple::propose: only governors can propose\");\n        require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, \"GovernorSimple::propose: proposal function information arity mismatch\");\n        require(targets.length != 0, \"GovernorSimple::propose: must provide actions\");\n        require(targets.length <= proposalMaxOperations, \"GovernorSimple::propose: too many actions\");\n\n        uint startBlock = block.number;\n\n        proposalCount++;\n        Proposal memory newProposal = Proposal({\n            id: proposalCount,\n            proposer: msg.sender,\n            targets: targets,\n            values: values,\n            signatures: signatures,\n            calldatas: calldatas,\n            startBlock: startBlock,\n            canceled: false,\n            queued: false,\n            executed: false\n        });\n\n        proposals[newProposal.id] = newProposal;\n\n        emit ProposalCreated(newProposal.id, msg.sender, targets, values, signatures, calldatas, startBlock, description);\n        return newProposal.id;\n    }\n\n    /**\n      * @notice Queues a proposal of state active\n      * @param proposalId The id of the proposal to queue\n      */\n    function queue(uint proposalId) external {\n        require(isAdmin(msg.sender), \"GovernorSimple::queue: only governors can queue\");\n        require(state(proposalId) == ProposalState.Active, \"GovernorSimple::queue: proposal can only be queued if it is active\");\n\n        Proposal storage proposal = proposals[proposalId];\n        proposal.queued = true;\n        for (uint i = 0; i < proposal.targets.length; i++) {\n            queueOrRevertInternal(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i]);\n        }\n        emit ProposalQueued(proposalId);\n    }\n\n    function queueOrRevertInternal(address target, uint value, string memory signature, bytes memory data) internal {\n        require(!timelock.queuedTransactions(keccak256(abi.encode(target, value, signature, data))), \"GovernorSimple::queueOrRevertInternal: identical proposal action already queued at eta\");\n        timelock.queueTransaction(target, value, signature, data, 0);\n    }\n\n    /**\n      * @notice Executes a queued proposal if eta has passed\n      * @param proposalId The id of the proposal to execute\n      */\n    function execute(uint proposalId) external payable {\n        require(isAdmin(msg.sender), \"GovernorSimple::execute: only governors can execute\");\n        require(state(proposalId) == ProposalState.Queued, \"GovernorSimple::execute: proposal can only be executed if it is queued\");\n\n        Proposal storage proposal = proposals[proposalId];\n        proposal.queued = false;\n        proposal.executed = true;\n        for (uint i = 0; i < proposal.targets.length; i++) {\n            timelock.executeTransaction{ value:proposal.values[i] }(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i], 0);\n        }\n        emit ProposalExecuted(proposalId);\n    }\n\n    /**\n      * @notice Cancels a proposal only if sender is a governor\n      * @param proposalId The id of the proposal to cancel\n      */\n    function cancel(uint proposalId) external {\n        require(isAdmin(msg.sender), \"GovernorSimple::cancel: only governors can cancel\");\n        require(state(proposalId) != ProposalState.Executed, \"GovernorSimple::cancel: cannot cancel executed proposal\");\n\n        Proposal storage proposal = proposals[proposalId];\n        proposal.canceled = true;\n        for (uint i = 0; i < proposal.targets.length; i++) {\n            timelock.cancelTransaction(proposal.targets[i], proposal.values[i], proposal.signatures[i], proposal.calldatas[i]);\n        }\n        emit ProposalCanceled(proposalId);\n    }\n\n    /**\n      * @notice Gets actions of a proposal\n      * @param proposalId the id of the proposal\n      */\n    function getActions(uint proposalId) external view returns (address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas) {\n        Proposal storage p = proposals[proposalId];\n        return (p.targets, p.values, p.signatures, p.calldatas);\n    }\n\n    /**\n      * @notice Gets the state of a proposal\n      * @param proposalId The id of the proposal\n      * @return Proposal state\n      */\n    function state(uint proposalId) public view returns (ProposalState) {\n        require(proposalCount >= proposalId, \"GovernorSimple::state: invalid proposal id\");\n        Proposal memory proposal = proposals[proposalId];\n        if (proposal.canceled) {\n            return ProposalState.Canceled;\n        } else if (proposal.queued) {\n            return ProposalState.Queued;\n        } else if (proposal.executed) {\n            return ProposalState.Executed;\n        } else {\n            return ProposalState.Active;\n        }\n    }\n\n    /// @notice Checks whether an account is a governor or not\n    function isAdmin(address account) public view returns (bool) {\n        for (uint i = 0; i < admins.length; i++) {\n            if (admins[i] == account) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * @notice Add new admin\n     * @param newAdminAddress Address of admin to add\n     */\n    function addAdmin(address newAdminAddress) external {\n        require(isAdmin(msg.sender), \"GovernorSimple::addAdmin: only governors can add governors\");\n        admins.push(newAdminAddress);\n    }\n\n    /**\n     * @notice Remove admin from admin array\n     * @param adminAddress Address of admin to remove\n     */\n    function removeAdmin(address adminAddress) external {\n        require(isAdmin(msg.sender), \"GovernorSimple::removeAdmin: only governors can remove governors\");\n        require(msg.sender != adminAddress, \"GovernorSimple::removeAdmin: cannot remove self as admin\"); // ensure there is always one admin\n\n        bool addressFound = false;\n\n        for (uint i = 0; i < admins.length; i++) {\n            if (admins[i] == adminAddress) {\n                admins[i] == admins[admins.length - 1];\n                addressFound = true;\n            }\n        }\n        if (addressFound) {\n            admins.pop();\n        }\n    }\n}"},{"file_path":"contracts/bridges/ronin/RoninBridgeReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../SweepableBridgeReceiver.sol\";\nimport {IERC165} from \"../../IERC165.sol\";\nimport {IAny2EVMMessageReceiver, Any2EVMMessage} from \"../../IAny2EVMMessageReceiver.sol\";\n\ncontract RoninBridgeReceiver is SweepableBridgeReceiver, IERC165, IAny2EVMMessageReceiver{\n    uint64 constant MAINNET_CHAIN_SELECTOR = 5009297550715157269;\n\n    function supportsInterface(\n        bytes4 interfaceId\n    ) public view virtual override returns (bool) {\n        return\n            interfaceId == type(IAny2EVMMessageReceiver).interfaceId ||\n            interfaceId == type(IERC165).interfaceId;\n    }\n\n    error InvalidRouter();\n    error InvalidChainSelector();\n\n    address public l2Router;\n\n    constructor(address l2Router_) {\n        l2Router = l2Router_;\n    }\n\n    function ccipReceive(Any2EVMMessage calldata message) external {\n        if (msg.sender != l2Router) revert InvalidRouter();\n        if(message.sourceChainSelector != MAINNET_CHAIN_SELECTOR) revert InvalidChainSelector();\n        processMessage(toAddress(message.sender), message.data);\n    }\n\n    function toAddress(bytes memory data) public pure returns (address addr) {\n        require(data.length >= 20, \"Invalid data length\");\n        return abi.decode(data, (address));\n    }\n}\n"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3FlashCallback.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Callback for IUniswapV3PoolActions#flash\n/// @notice Any contract that calls IUniswapV3PoolActions#flash must implement this interface\ninterface IUniswapV3FlashCallback {\n    /// @notice Called to `msg.sender` after transferring to the recipient from IUniswapV3Pool#flash.\n    /// @dev In the implementation you must repay the pool the tokens sent by flash plus the computed fee amounts.\n    /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n    /// @param fee0 The fee amount in token0 due to the pool by the end of the flash\n    /// @param fee1 The fee amount in token1 due to the pool by the end of the flash\n    /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#flash call\n    function uniswapV3FlashCallback(\n        uint256 fee0,\n        uint256 fee1,\n        bytes calldata data\n    ) external;\n}\n"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-periphery/contracts/base/PeripheryPayments.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.7.5;\n\nimport '../../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nimport '../interfaces/IPeripheryPayments.sol';\nimport '../interfaces/external/IWETH9.sol';\n\nimport '../libraries/TransferHelper.sol';\n\nimport './PeripheryImmutableState.sol';\n\nabstract contract PeripheryPayments is IPeripheryPayments, PeripheryImmutableState {\n    /// @inheritdoc IPeripheryPayments\n    function unwrapWETH9(uint256 amountMinimum, address recipient) public payable override {\n        uint256 balanceWETH9 = IWETH9(WETH9).balanceOf(address(this));\n        require(balanceWETH9 >= amountMinimum, 'Insufficient WETH9');\n\n        if (balanceWETH9 > 0) {\n            IWETH9(WETH9).withdraw(balanceWETH9);\n            TransferHelper.safeTransferETH(recipient, balanceWETH9);\n        }\n    }\n\n    /// @inheritdoc IPeripheryPayments\n    function sweepToken(\n        address token,\n        uint256 amountMinimum,\n        address recipient\n    ) public payable override {\n        uint256 balanceToken = IERC20(token).balanceOf(address(this));\n        require(balanceToken >= amountMinimum, 'Insufficient token');\n\n        if (balanceToken > 0) {\n            TransferHelper.safeTransfer(token, recipient, balanceToken);\n        }\n    }\n\n    /// @inheritdoc IPeripheryPayments\n    function refundETH() external payable override {\n        if (address(this).balance > 0) TransferHelper.safeTransferETH(msg.sender, address(this).balance);\n    }\n\n    /// @param token The token to pay\n    /// @param payer The entity that must pay\n    /// @param recipient The entity that will receive payment\n    /// @param value The amount to pay\n    function pay(\n        address token,\n        address payer,\n        address recipient,\n        uint256 value\n    ) internal {\n        if (token == WETH9 && address(this).balance >= value) {\n            // pay with WETH9\n            IWETH9(WETH9).deposit{value: value}(); // wrap only what is needed to pay\n            IWETH9(WETH9).transfer(recipient, value);\n        } else if (payer == address(this)) {\n            // pay with tokens already in the contract (for the exact input multihop case)\n            TransferHelper.safeTransfer(token, recipient, value);\n        } else {\n            // pull payment\n            TransferHelper.safeTransferFrom(token, payer, recipient, value);\n        }\n    }\n}\n"},{"file_path":"contracts/pricefeeds/EzETHExchangeRatePriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/renzo/IBalancerRateProvider.sol\";\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title ezETH Scaling price feed\n * @notice A custom price feed that scales up or down the price received from an underlying Renzo ezETH / ETH exchange rate price feed and returns the result\n * @author Compound\n */\ncontract EzETHExchangeRatePriceFeed is IPriceFeed {\n    /** Custom errors **/\n    error InvalidInt256();\n    error BadDecimals();\n\n    /// @notice Version of the price feed\n    uint public constant VERSION = 1;\n\n    /// @notice Description of the price feed\n    string public description;\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice ezETH price feed where prices are fetched from\n    address public immutable underlyingPriceFeed;\n\n    /// @notice Whether or not the price should be upscaled\n    bool internal immutable shouldUpscale;\n\n    /// @notice The amount to upscale or downscale the price by\n    int256 internal immutable rescaleFactor;\n\n    /**\n     * @notice Construct a new ezETH scaling price feed\n     * @param ezETHRateProvider The address of the underlying price feed to fetch prices from\n     * @param decimals_ The number of decimals for the returned prices\n     **/\n    constructor(address ezETHRateProvider, uint8 decimals_, string memory description_) {\n        underlyingPriceFeed = ezETHRateProvider;\n        if (decimals_ > 18) revert BadDecimals();\n        decimals = decimals_;\n        description = description_;\n\n        uint8 ezETHRateProviderDecimals = 18;\n        // Note: Solidity does not allow setting immutables in if/else statements\n        shouldUpscale = ezETHRateProviderDecimals < decimals_ ? true : false;\n        rescaleFactor = (shouldUpscale\n            ? signed256(10 ** (decimals_ - ezETHRateProviderDecimals))\n            : signed256(10 ** (ezETHRateProviderDecimals - decimals_))\n        );\n    }\n\n    /**\n     * @notice Price for the latest round\n     * @return roundId Round id from the underlying price feed\n     * @return answer Latest price for the asset in terms of ETH\n     * @return startedAt Timestamp when the round was started; passed on from underlying price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from underlying price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed\n     **/\n    function latestRoundData() override external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        uint256 rate = IBalancerRateProvider(underlyingPriceFeed).getRate();\n        // protocol uses only the answer value. Other data fields are not provided by the underlying pricefeed and are not used in Comet protocol\n        // https://etherscan.io/address/0x387dBc0fB00b26fb085aa658527D5BE98302c84C#readProxyContract\n        return (1, scalePrice(signed256(rate)), block.timestamp, block.timestamp, 1);\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 scalePrice(int256 price) internal view returns (int256) {\n        int256 scaledPrice;\n        if (shouldUpscale) {\n            scaledPrice = price * rescaleFactor;\n        } else {\n            scaledPrice = price / rescaleFactor;\n        }\n        return scaledPrice;\n    }\n\n    /**\n     * @notice Price for the latest round\n     * @return The version of the price feed contract\n     **/\n    function version() external pure returns (uint256) {\n        return VERSION;\n    }\n}\n"},{"file_path":"contracts/bridges/linea/IMessageService.sol","source_code":"pragma solidity 0.8.15;\n\ninterface IMessageService {\n  function sender() external view returns (address);\n}\n"},{"file_path":"contracts/test/CometModifiedFactory.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometModified.sol\";\nimport \"../CometConfiguration.sol\";\n\ncontract CometModifiedFactory is CometConfiguration {\n    function clone(Configuration calldata config) external returns (address) {\n        return address(new CometModified(config));\n    }\n}"},{"file_path":"contracts/CometRewards.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometInterface.sol\";\nimport \"./ERC20.sol\";\n\n/**\n * @title Compound's CometRewards Contract\n * @notice Hold and claim token rewards\n * @author Compound\n */\ncontract CometRewards {\n    struct RewardConfig {\n        address token;\n        uint64 rescaleFactor;\n        bool shouldUpscale;\n        // Note: We define new variables after existing variables to keep interface backwards-compatible\n        uint256 multiplier;\n    }\n\n    struct RewardOwed {\n        address token;\n        uint owed;\n    }\n\n    /// @notice The governor address which controls the contract\n    address public governor;\n\n    /// @notice Reward token address per Comet instance\n    mapping(address => RewardConfig) public rewardConfig;\n\n    /// @notice Rewards claimed per Comet instance and user account\n    mapping(address => mapping(address => uint)) public rewardsClaimed;\n\n    /// @dev The scale for factors\n    uint256 internal constant FACTOR_SCALE = 1e18;\n\n    /** Custom events **/\n\n    event GovernorTransferred(address indexed oldGovernor, address indexed newGovernor);\n    event RewardsClaimedSet(address indexed user, address indexed comet, uint256 amount);\n    event RewardClaimed(address indexed src, address indexed recipient, address indexed token, uint256 amount);\n\n    /** Custom errors **/\n\n    error AlreadyConfigured(address);\n    error BadData();\n    error InvalidUInt64(uint);\n    error NotPermitted(address);\n    error NotSupported(address);\n    error TransferOutFailed(address, uint);\n\n    /**\n     * @notice Construct a new rewards pool\n     * @param governor_ The governor who will control the contract\n     */\n    constructor(address governor_) {\n        governor = governor_;\n    }\n\n    /**\n     * @notice Set the reward token for a Comet instance\n     * @param comet The protocol instance\n     * @param token The reward token address\n     * @param multiplier The multiplier for converting a unit of accrued tracking to a unit of the reward token\n     */\n    function setRewardConfigWithMultiplier(address comet, address token, uint256 multiplier) public {\n        if (msg.sender != governor) revert NotPermitted(msg.sender);\n        if (rewardConfig[comet].token != address(0)) revert AlreadyConfigured(comet);\n\n        uint64 accrualScale = CometInterface(comet).baseAccrualScale();\n        uint8 tokenDecimals = ERC20(token).decimals();\n        uint64 tokenScale = safe64(10 ** tokenDecimals);\n        if (accrualScale > tokenScale) {\n            rewardConfig[comet] = RewardConfig({\n                token: token,\n                rescaleFactor: accrualScale / tokenScale,\n                shouldUpscale: false,\n                multiplier: multiplier\n            });\n        } else {\n            rewardConfig[comet] = RewardConfig({\n                token: token,\n                rescaleFactor: tokenScale / accrualScale,\n                shouldUpscale: true,\n                multiplier: multiplier\n            });\n        }\n    }\n\n    /**\n     * @notice Set the reward token for a Comet instance\n     * @param comet The protocol instance\n     * @param token The reward token address\n     */\n    function setRewardConfig(address comet, address token) external {\n        setRewardConfigWithMultiplier(comet, token, FACTOR_SCALE);\n    }\n\n    /**\n     * @notice Set the rewards claimed for a list of users\n     * @param comet The protocol instance to populate the data for\n     * @param users The list of users to populate the data for\n     * @param claimedAmounts The list of claimed amounts to populate the data with\n     */\n    function setRewardsClaimed(address comet, address[] calldata users, uint[] calldata claimedAmounts) external {\n        if (msg.sender != governor) revert NotPermitted(msg.sender);\n        if (users.length != claimedAmounts.length) revert BadData();\n\n        for (uint i = 0; i < users.length; ) {\n            rewardsClaimed[comet][users[i]] = claimedAmounts[i];\n            emit RewardsClaimedSet(users[i], comet, claimedAmounts[i]);\n            unchecked { i++; }\n        }\n    }\n\n    /**\n     * @notice Withdraw tokens from the contract\n     * @param token The reward token address\n     * @param to Where to send the tokens\n     * @param amount The number of tokens to withdraw\n     */\n    function withdrawToken(address token, address to, uint amount) external {\n        if (msg.sender != governor) revert NotPermitted(msg.sender);\n\n        doTransferOut(token, to, amount);\n    }\n\n    /**\n     * @notice Transfers the governor rights to a new address\n     * @param newGovernor The address of the new governor\n     */\n    function transferGovernor(address newGovernor) external {\n        if (msg.sender != governor) revert NotPermitted(msg.sender);\n\n        address oldGovernor = governor;\n        governor = newGovernor;\n        emit GovernorTransferred(oldGovernor, newGovernor);\n    }\n\n    /**\n     * @notice Calculates the amount of a reward token owed to an account\n     * @param comet The protocol instance\n     * @param account The account to check rewards for\n     */\n    function getRewardOwed(address comet, address account) external returns (RewardOwed memory) {\n        RewardConfig memory config = rewardConfig[comet];\n        if (config.token == address(0)) revert NotSupported(comet);\n\n        CometInterface(comet).accrueAccount(account);\n\n        uint claimed = rewardsClaimed[comet][account];\n        uint accrued = getRewardAccrued(comet, account, config);\n\n        uint owed = accrued > claimed ? accrued - claimed : 0;\n        return RewardOwed(config.token, owed);\n    }\n\n    /**\n     * @notice Claim rewards of token type from a comet instance to owner address\n     * @param comet The protocol instance\n     * @param src The owner to claim for\n     * @param shouldAccrue Whether or not to call accrue first\n     */\n    function claim(address comet, address src, bool shouldAccrue) external {\n        claimInternal(comet, src, src, shouldAccrue);\n    }\n\n    /**\n     * @notice Claim rewards of token type from a comet instance to a target address\n     * @param comet The protocol instance\n     * @param src The owner to claim for\n     * @param to The address to receive the rewards\n     */\n    function claimTo(address comet, address src, address to, bool shouldAccrue) external {\n        if (!CometInterface(comet).hasPermission(src, msg.sender)) revert NotPermitted(msg.sender);\n\n        claimInternal(comet, src, to, shouldAccrue);\n    }\n\n    /**\n     * @dev Claim to, assuming permitted\n     */\n    function claimInternal(address comet, address src, address to, bool shouldAccrue) internal {\n        RewardConfig memory config = rewardConfig[comet];\n        if (config.token == address(0)) revert NotSupported(comet);\n\n        if (shouldAccrue) {\n            CometInterface(comet).accrueAccount(src);\n        }\n\n        uint claimed = rewardsClaimed[comet][src];\n        uint accrued = getRewardAccrued(comet, src, config);\n\n        if (accrued > claimed) {\n            uint owed = accrued - claimed;\n            rewardsClaimed[comet][src] = accrued;\n            doTransferOut(config.token, to, owed);\n\n            emit RewardClaimed(src, to, config.token, owed);\n        }\n    }\n\n    /**\n     * @dev Calculates the reward accrued for an account on a Comet deployment\n     */\n    function getRewardAccrued(address comet, address account, RewardConfig memory config) internal view returns (uint) {\n        uint accrued = CometInterface(comet).baseTrackingAccrued(account);\n\n        if (config.shouldUpscale) {\n            accrued *= config.rescaleFactor;\n        } else {\n            accrued /= config.rescaleFactor;\n        }\n        return accrued * config.multiplier / FACTOR_SCALE;\n    }\n\n    /**\n     * @dev Safe ERC20 transfer out\n     */\n    function doTransferOut(address token, address to, uint amount) internal {\n        bool success = ERC20(token).transfer(to, amount);\n        if (!success) revert TransferOutFailed(to, amount);\n    }\n\n    /**\n     * @dev Safe cast to uint64\n     */\n    function safe64(uint n) internal pure returns (uint64) {\n        if (n > type(uint64).max) revert InvalidUInt64(n);\n        return uint64(n);\n    }\n}"},{"file_path":"@openzeppelin/contracts/access/AccessControl.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address => bool) members;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with a standardized message including the required role.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     *\n     * _Available since v4.1._\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n        return _roles[role].members[account];\n    }\n\n    /**\n     * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n     * Overriding this function changes the behavior of the {onlyRole} modifier.\n     *\n     * Format of the revert message is described in {_checkRole}.\n     *\n     * _Available since v4.6._\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Revert with a standard message if `account` is missing `role`.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        \"AccessControl: account \",\n                        Strings.toHexString(account),\n                        \" is missing role \",\n                        Strings.toHexString(uint256(role), 32)\n                    )\n                )\n            );\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address account) public virtual override {\n        require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event. Note that unlike {grantRole}, this function doesn't perform any\n     * checks on the calling account.\n     *\n     * May emit a {RoleGranted} event.\n     *\n     * [WARNING]\n     * ====\n     * This function should only be called from the constructor when setting\n     * up the initial roles for the system.\n     *\n     * Using this function in any other way is effectively circumventing the admin\n     * system imposed by {AccessControl}.\n     * ====\n     *\n     * NOTE: This function is deprecated in favor of {_grantRole}.\n     */\n    function _setupRole(bytes32 role, address account) internal virtual {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual {\n        if (!hasRole(role, account)) {\n            _roles[role].members[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n        }\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual {\n        if (hasRole(role, account)) {\n            _roles[role].members[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n        }\n    }\n}\n"},{"file_path":"contracts/IProxy.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @dev Interface for interacting with a basic proxy.\n * Note Not a comprehensive interface\n */\ninterface IProxy {\n    function implementation() external view returns (address);\n}\n"},{"file_path":"contracts/test/FaucetToken.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title Standard ERC20 token\n * @dev Implementation of the basic standard token.\n *  See https://github.com/ethereum/EIPs/issues/20\n */\ncontract StandardToken {\n    string public name;\n    string public symbol;\n    uint8 public decimals;\n    uint256 public totalSupply;\n    mapping (address => mapping (address => uint256)) public allowance;\n    mapping(address => uint256) public balanceOf;\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n        totalSupply = _initialAmount;\n        balanceOf[msg.sender] = _initialAmount;\n        name = _tokenName;\n        symbol = _tokenSymbol;\n        decimals = _decimalUnits;\n    }\n\n    function transfer(address dst, uint256 amount) public virtual returns (bool) {\n        require(amount <= balanceOf[msg.sender], \"ERC20: transfer amount exceeds balance\");\n        balanceOf[msg.sender] = balanceOf[msg.sender] - amount;\n        balanceOf[dst] = balanceOf[dst] + amount;\n        emit Transfer(msg.sender, dst, amount);\n        return true;\n    }\n\n    function transferFrom(address src, address dst, uint256 amount) public virtual returns (bool) {\n        require(amount <= allowance[src][msg.sender], \"ERC20: transfer amount exceeds allowance\");\n        require(amount <= balanceOf[src], \"ERC20: transfer amount exceeds balance\");\n        allowance[src][msg.sender] = allowance[src][msg.sender] - amount;\n        balanceOf[src] = balanceOf[src] - amount;\n        balanceOf[dst] = balanceOf[dst] + amount;\n        emit Transfer(src, dst, amount);\n        return true;\n    }\n\n    function approve(address _spender, uint256 amount) external returns (bool) {\n        allowance[msg.sender][_spender] = amount;\n        emit Approval(msg.sender, _spender, amount);\n        return true;\n    }\n}\n\n/**\n * @title The Compound Faucet Test Token\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract FaucetToken is StandardToken {\n    constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol)\n        StandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n    }\n\n    function allocateTo(address _owner, uint256 value) public {\n        balanceOf[_owner] += value;\n        totalSupply += value;\n        emit Transfer(address(this), _owner, value);\n    }\n}\n"},{"file_path":"contracts/test/SimplePriceFeed.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\ncontract SimplePriceFeed is AggregatorV3Interface {\n    string public constant override description = \"Mock Chainlink price aggregator\";\n\n    uint public constant override version = 1;\n\n    uint8 public immutable override decimals;\n\n    uint80 internal roundId;\n    int256 internal answer;\n    uint256 internal startedAt;\n    uint256 internal updatedAt;\n    uint80 internal answeredInRound;\n\n    constructor(int answer_, uint8 decimals_) {\n        answer = answer_;\n        decimals = decimals_;\n    }\n\n    function setRoundData(\n        uint80 roundId_,\n        int256 answer_,\n        uint256 startedAt_,\n        uint256 updatedAt_,\n        uint80 answeredInRound_\n    ) public {\n        roundId = roundId_;\n        answer = answer_;\n        startedAt = startedAt_;\n        updatedAt = updatedAt_;\n        answeredInRound = answeredInRound_;\n    }\n\n    function getRoundData(uint80 roundId_) override external view returns (uint80, int256, uint256, uint256, uint80) {\n        return (roundId_, answer, startedAt, updatedAt, answeredInRound);\n    }\n\n    function latestRoundData() override external view returns (uint80, int256, uint256, uint256, uint80) {\n        return (roundId, answer, startedAt, updatedAt, answeredInRound);\n    }\n}\n"},{"file_path":"contracts/ScrollComet.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometMainInterface.sol\";\nimport \"./ERC20.sol\";\nimport \"./IPriceFeed.sol\";\n\n/**\n * @title Compound's Comet Contract on Scroll\n * @notice An efficient monolithic money market protocol\n * @author Compound\n */\ncontract ScrollComet 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    /** Collateral asset configuration (packed) **/\n\n    uint256 internal immutable asset00_a;\n    uint256 internal immutable asset00_b;\n    uint256 internal immutable asset01_a;\n    uint256 internal immutable asset01_b;\n    uint256 internal immutable asset02_a;\n    uint256 internal immutable asset02_b;\n    uint256 internal immutable asset03_a;\n    uint256 internal immutable asset03_b;\n    uint256 internal immutable asset04_a;\n    uint256 internal immutable asset04_b;\n    uint256 internal immutable asset05_a;\n    uint256 internal immutable asset05_b;\n    uint256 internal immutable asset06_a;\n    uint256 internal immutable asset06_b;\n    uint256 internal immutable asset07_a;\n    uint256 internal immutable asset07_b;\n    uint256 internal immutable asset08_a;\n    uint256 internal immutable asset08_b;\n    uint256 internal immutable asset09_a;\n    uint256 internal immutable asset09_b;\n    uint256 internal immutable asset10_a;\n    uint256 internal immutable asset10_b;\n    uint256 internal immutable asset11_a;\n    uint256 internal immutable asset11_b;\n    uint256 internal immutable asset12_a;\n    uint256 internal immutable asset12_b;\n    uint256 internal immutable asset13_a;\n    uint256 internal immutable asset13_b;\n    uint256 internal immutable asset14_a;\n    uint256 internal immutable asset14_b;\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_ = ERC20(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) 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        (asset00_a, asset00_b) = getPackedAssetInternal(config.assetConfigs, 0);\n        (asset01_a, asset01_b) = getPackedAssetInternal(config.assetConfigs, 1);\n        (asset02_a, asset02_b) = getPackedAssetInternal(config.assetConfigs, 2);\n        (asset03_a, asset03_b) = getPackedAssetInternal(config.assetConfigs, 3);\n        (asset04_a, asset04_b) = getPackedAssetInternal(config.assetConfigs, 4);\n        (asset05_a, asset05_b) = getPackedAssetInternal(config.assetConfigs, 5);\n        (asset06_a, asset06_b) = getPackedAssetInternal(config.assetConfigs, 6);\n        (asset07_a, asset07_b) = getPackedAssetInternal(config.assetConfigs, 7);\n        (asset08_a, asset08_b) = getPackedAssetInternal(config.assetConfigs, 8);\n        (asset09_a, asset09_b) = getPackedAssetInternal(config.assetConfigs, 9);\n        (asset10_a, asset10_b) = getPackedAssetInternal(config.assetConfigs, 10);\n        (asset11_a, asset11_b) = getPackedAssetInternal(config.assetConfigs, 11);\n        (asset12_a, asset12_b) = getPackedAssetInternal(config.assetConfigs, 12);\n        (asset13_a, asset13_b) = getPackedAssetInternal(config.assetConfigs, 13);\n        (asset14_a, asset14_b) = getPackedAssetInternal(config.assetConfigs, 14);\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     * @dev Checks and gets the packed asset info for storage\n     */\n    function getPackedAssetInternal(AssetConfig[] memory assetConfigs, uint i) internal view returns (uint256, uint256) {\n        AssetConfig memory assetConfig;\n        if (i < assetConfigs.length) {\n            assembly {\n                assetConfig := mload(add(add(assetConfigs, 0x20), mul(i, 0x20)))\n            }\n        } else {\n            return (0, 0);\n        }\n        address asset = assetConfig.asset;\n        address priceFeed = assetConfig.priceFeed;\n        uint8 decimals_ = assetConfig.decimals;\n\n        // Short-circuit if asset is nil\n        if (asset == address(0)) {\n            return (0, 0);\n        }\n\n        // Sanity check price feed and asset decimals\n        if (IPriceFeed(priceFeed).decimals() != PRICE_FEED_DECIMALS) revert BadDecimals();\n        if (ERC20(asset).decimals() != decimals_) revert BadDecimals();\n\n        // Ensure collateral factors are within range\n        if (assetConfig.borrowCollateralFactor >= assetConfig.liquidateCollateralFactor) revert BorrowCFTooLarge();\n        if (assetConfig.liquidateCollateralFactor > MAX_COLLATERAL_FACTOR) revert LiquidateCFTooLarge();\n\n        unchecked {\n            // Keep 4 decimals for each factor\n            uint64 descale = FACTOR_SCALE / 1e4;\n            uint16 borrowCollateralFactor = uint16(assetConfig.borrowCollateralFactor / descale);\n            uint16 liquidateCollateralFactor = uint16(assetConfig.liquidateCollateralFactor / descale);\n            uint16 liquidationFactor = uint16(assetConfig.liquidationFactor / descale);\n\n            // Be nice and check descaled values are still within range\n            if (borrowCollateralFactor >= liquidateCollateralFactor) revert BorrowCFTooLarge();\n\n            // Keep whole units of asset for supply cap\n            uint64 supplyCap = uint64(assetConfig.supplyCap / (10 ** decimals_));\n\n            uint256 word_a = (uint160(asset) << 0 |\n                              uint256(borrowCollateralFactor) << 160 |\n                              uint256(liquidateCollateralFactor) << 176 |\n                              uint256(liquidationFactor) << 192);\n            uint256 word_b = (uint160(priceFeed) << 0 |\n                              uint256(decimals_) << 160 |\n                              uint256(supplyCap) << 168);\n\n            return (word_a, word_b);\n        }\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        if (i >= numAssets) revert BadAsset();\n\n        uint256 word_a;\n        uint256 word_b;\n\n        if (i == 0) {\n            word_a = asset00_a;\n            word_b = asset00_b;\n        } else if (i == 1) {\n            word_a = asset01_a;\n            word_b = asset01_b;\n        } else if (i == 2) {\n            word_a = asset02_a;\n            word_b = asset02_b;\n        } else if (i == 3) {\n            word_a = asset03_a;\n            word_b = asset03_b;\n        } else if (i == 4) {\n            word_a = asset04_a;\n            word_b = asset04_b;\n        } else if (i == 5) {\n            word_a = asset05_a;\n            word_b = asset05_b;\n        } else if (i == 6) {\n            word_a = asset06_a;\n            word_b = asset06_b;\n        } else if (i == 7) {\n            word_a = asset07_a;\n            word_b = asset07_b;\n        } else if (i == 8) {\n            word_a = asset08_a;\n            word_b = asset08_b;\n        } else if (i == 9) {\n            word_a = asset09_a;\n            word_b = asset09_b;\n        } else if (i == 10) {\n            word_a = asset10_a;\n            word_b = asset10_b;\n        } else if (i == 11) {\n            word_a = asset11_a;\n            word_b = asset11_b;\n        } else if (i == 12) {\n            word_a = asset12_a;\n            word_b = asset12_b;\n        } else if (i == 13) {\n            word_a = asset13_a;\n            word_b = asset13_b;\n        } else if (i == 14) {\n            word_a = asset14_a;\n            word_b = asset14_b;\n        } else {\n            revert Absurd();\n        }\n\n        address asset = address(uint160(word_a & type(uint160).max));\n        uint64 rescale = FACTOR_SCALE / 1e4;\n        uint64 borrowCollateralFactor = uint64(((word_a >> 160) & type(uint16).max) * rescale);\n        uint64 liquidateCollateralFactor = uint64(((word_a >> 176) & type(uint16).max) * rescale);\n        uint64 liquidationFactor = uint64(((word_a >> 192) & type(uint16).max) * rescale);\n\n        address priceFeed = address(uint160(word_b & type(uint160).max));\n        uint8 decimals_ = uint8(((word_b >> 160) & type(uint8).max));\n        uint64 scale = uint64(10 ** decimals_);\n        uint128 supplyCap = uint128(((word_b >> 168) & type(uint64).max) * scale);\n\n        return AssetInfo({\n            offset: i,\n            asset: asset,\n            priceFeed: priceFeed,\n            scale: scale,\n            borrowCollateralFactor: borrowCollateralFactor,\n            liquidateCollateralFactor: liquidateCollateralFactor,\n            liquidationFactor: liquidationFactor,\n            supplyCap: supplyCap\n         });\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        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     * @notice Accrue interest and rewards for an account\n     **/\n    function accrueAccount(address account) override external {\n        accrueInternal();\n\n        UserBasic memory basic = userBasic[account];\n        updateBasePrincipal(account, basic, basic.principal);\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        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        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 ERC20(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 = ERC20(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        int liquidity = signedMulPrice(\n            presentValue(principal),\n            getPrice(baseTokenPriceFeed),\n            uint64(baseScale)\n        );\n\n        for (uint8 i = 0; i < numAssets; ) {\n            if (isInAsset(assetsIn, i)) {\n                if (liquidity >= 0) {\n                    return true;\n                }\n\n                AssetInfo memory asset = getAssetInfo(i);\n                uint 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            unchecked { i++; }\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    function isLiquidatable(address account) override public view returns (bool) {\n        int104 principal = userBasic[account].principal;\n\n        if (principal >= 0) {\n            return false;\n        }\n\n        uint16 assetsIn = userBasic[account].assetsIn;\n        int liquidity = signedMulPrice(\n            presentValue(principal),\n            getPrice(baseTokenPriceFeed),\n            uint64(baseScale)\n        );\n\n        for (uint8 i = 0; i < numAssets; ) {\n            if (isInAsset(assetsIn, i)) {\n                if (liquidity >= 0) {\n                    return false;\n                }\n\n                AssetInfo memory asset = getAssetInfo(i);\n                uint newAmount = mulPrice(\n                    userCollateral[account][asset.asset].balance,\n                    getPrice(asset.priceFeed),\n                    asset.scale\n                );\n                liquidity += signed256(mulFactor(\n                    newAmount,\n                    asset.liquidateCollateralFactor\n                ));\n            }\n            unchecked { i++; }\n        }\n\n        return liquidity < 0;\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     * @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     */\n    function isInAsset(uint16 assetsIn, uint8 assetOffset) internal pure returns (bool) {\n        return (assetsIn & (uint16(1) << assetOffset) != 0);\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            userBasic[account].assetsIn |= (uint16(1) << assetInfo.offset);\n        } else if (initialUserBalance != 0 && finalUserBalance == 0) {\n            // clear bit for asset\n            userBasic[account].assetsIn &= ~(uint16(1) << assetInfo.offset);\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, assumes no fee is charged and amount is transferred\n     */\n    function doTransferIn(address asset, address from, uint amount) internal {\n        bool success = ERC20(asset).transferFrom(from, address(this), amount);\n        if (!success) revert TransferInFailed();\n    }\n\n    /**\n     * @dev Safe ERC20 transfer out\n     */\n    function doTransferOut(address asset, address to, uint amount) internal {\n        bool success = ERC20(asset).transfer(to, amount);\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, 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, 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(msg.sender, 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 operator, address from, address dst, address asset, uint amount) internal {\n        if (isSupplyPaused()) revert Paused();\n        if (!hasPermission(from, operator)) revert Unauthorized();\n\n        if (asset == baseToken) {\n            if (amount == type(uint256).max) {\n                amount = borrowBalanceOf(dst);\n            }\n            return supplyBase(from, dst, amount);\n        } else {\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        doTransferIn(baseToken, from, amount);\n\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        doTransferIn(asset, from, amount);\n\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\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 {\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            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 (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall();\n            if (!isBorrowCollateralized(src)) revert NotCollateralized();\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        updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew);\n        updateAssetsIn(dst, assetInfo, dstCollateral, dstCollateralNew);\n\n        // Note: no accrue interest, BorrowCF < LiquidationCF covers small changes\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 {\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            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 (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall();\n            if (!isBorrowCollateralized(src)) revert NotCollateralized();\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    function withdrawCollateral(address src, address to, address asset, uint128 amount) internal {\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        updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew);\n\n        // Note: no accrue interest, BorrowCF < LiquidationCF covers small changes\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        liquidatorPoints[absorber] = points;\n    }\n\n    /**\n     * @dev Transfer user's collateral and debt to the protocol itself.\n     */\n    function absorbInternal(address absorber, address account) internal {\n        if (!isLiquidatable(account)) 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\n        uint256 basePrice = getPrice(baseTokenPriceFeed);\n        uint256 deltaValue = 0;\n\n        for (uint8 i = 0; i < numAssets; ) {\n            if (isInAsset(assetsIn, i)) {\n                AssetInfo memory assetInfo = getAssetInfo(i);\n                address asset = assetInfo.asset;\n                uint128 seizeAmount = userCollateral[account][asset].balance;\n                userCollateral[account][asset].balance = 0;\n                totalsCollateral[asset].totalSupplyAsset -= seizeAmount;\n\n                uint256 value = mulPrice(seizeAmount, getPrice(assetInfo.priceFeed), 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\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 {\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        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        uint256 assetPrice = getPrice(assetInfo.priceFeed);\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        uint256 assetPriceDiscounted = mulFactor(assetPrice, FACTOR_SCALE - discountFactor);\n        uint256 basePrice = getPrice(baseTokenPriceFeed);\n        // # of collateral assets\n        // = (TotalValueOfBaseAmount / DiscountedPriceOfCollateralAsset) * assetScale\n        // = ((basePrice * baseAmount / baseScale) / assetPriceDiscounted) * 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     * @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        ERC20(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}\n"},{"file_path":"contracts/pricefeeds/PriceFeedWith4626Support.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport \"../IERC4626.sol\";\nimport \"../IPriceFeed.sol\";\n\n/**\n * @title Price feed for ERC4626 assets\n * @notice A custom price feed that calculates the price for an ERC4626 asset\n * @author Compound\n */\ncontract PriceFeedWith4626Support is IPriceFeed {\n    /** Custom errors **/\n    error BadDecimals();\n    error InvalidInt256();\n\n    /// @notice Version of the price feed\n    uint public constant VERSION = 1;\n\n    /// @notice Description of the price feed\n    string public override description;\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable override decimals;\n\n    /// @notice Number of decimals for the 4626 rate provider\n    uint8 internal immutable rateProviderDecimals;\n\n    /// @notice Number of decimals for the underlying asset\n    uint8 internal immutable underlyingDecimals;\n\n    /// @notice 4626 rate provider\n    address public immutable rateProvider;\n\n    /// @notice Chainlink oracle for the underlying asset\n    address public immutable underlyingPriceFeed;\n\n    /// @notice Combined scale of the two underlying price feeds\n    int public immutable combinedScale;\n\n    /// @notice Scale of this price feed\n    int public immutable priceFeedScale;\n\n    /**\n     * @notice Construct a new 4626 price feed\n     * @param rateProvider_ The address of the 4626 rate provider\n     * @param underlyingPriceFeed_ The address of the underlying asset price feed to fetch prices from\n     * @param decimals_ The number of decimals for the returned prices\n     * @param description_ The description of the price feed\n     **/\n    constructor(address rateProvider_, address underlyingPriceFeed_, uint8 decimals_, string memory description_) {\n        rateProvider = rateProvider_;\n        underlyingPriceFeed = underlyingPriceFeed_;\n        rateProviderDecimals = IERC4626(rateProvider_).decimals();\n        underlyingDecimals = AggregatorV3Interface(underlyingPriceFeed_).decimals();\n        combinedScale = signed256(10 ** (rateProviderDecimals + underlyingDecimals));\n        description = description_;\n\n        if (decimals_ > 18) revert BadDecimals();\n        decimals = decimals_;\n        priceFeedScale = int256(10 ** decimals);\n    }\n\n    /**\n     * @notice Get the latest price for the underlying asset\n     * @return roundId Round id from the underlying asset price feed\n     * @return answer Latest price for the underlying asset\n     * @return startedAt Timestamp when the round was started; passed on from the underlying asset price feed\n     * @return updatedAt Timestamp when the round was last updated; passed on from the underlying asset price feed\n     * @return answeredInRound Round id in which the answer was computed; passed on from the underlying asset price feed\n     **/\n    function latestRoundData() override external view returns (uint80, int256, uint256, uint256, uint80) {\n        uint256 rate = IERC4626(rateProvider).convertToAssets(10**rateProviderDecimals);\n        (uint80 roundId_, int256 underlyingPrice, uint256 startedAt_, uint256 updatedAt_, uint80 answeredInRound_) = AggregatorV3Interface(underlyingPriceFeed).latestRoundData();\n\n        if (rate <= 0 || underlyingPrice <= 0) return (roundId_, 0, startedAt_, updatedAt_, answeredInRound_);\n\n        int256 price = signed256(rate) * underlyingPrice * priceFeedScale / combinedScale;\n        return (roundId_, price, startedAt_, updatedAt_, answeredInRound_);\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    /**\n     * @notice Price for the latest round\n     * @return The version of the price feed contract\n     **/\n    function version() external pure returns (uint256) {\n        return VERSION;\n    }\n}"},{"file_path":"contracts/test/NonStandardFaucetToken.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @title Non-standard ERC20 token\n * @dev Implementation of the basic standard token.\n *  See https://github.com/ethereum/EIPs/issues/20\n * @dev Note: `transfer` and `transferFrom` do not return a boolean\n */\ncontract NonStandardToken {\n    string public name;\n    string public symbol;\n    uint8 public decimals;\n    uint256 public totalSupply;\n    mapping (address => mapping (address => uint256)) public allowance;\n    mapping(address => uint256) public balanceOf;\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol) {\n        totalSupply = _initialAmount;\n        balanceOf[msg.sender] = _initialAmount;\n        name = _tokenName;\n        symbol = _tokenSymbol;\n        decimals = _decimalUnits;\n    }\n\n    function transfer(address dst, uint256 amount) external virtual {\n        require(amount <= balanceOf[msg.sender], \"ERC20: transfer amount exceeds balance\");\n        balanceOf[msg.sender] = balanceOf[msg.sender] - amount;\n        balanceOf[dst] = balanceOf[dst] + amount;\n        emit Transfer(msg.sender, dst, amount);\n    }\n\n    function transferFrom(address src, address dst, uint256 amount) external virtual {\n        require(amount <= allowance[src][msg.sender], \"ERC20: transfer amount exceeds allowance\");\n        require(amount <= balanceOf[src], \"ERC20: transfer amount exceeds balance\");\n        allowance[src][msg.sender] = allowance[src][msg.sender] - amount;\n        balanceOf[src] = balanceOf[src] - amount;\n        balanceOf[dst] = balanceOf[dst] + amount;\n        emit Transfer(src, dst, amount);\n    }\n\n    function approve(address _spender, uint256 amount) external returns (bool) {\n        allowance[msg.sender][_spender] = amount;\n        emit Approval(msg.sender, _spender, amount);\n        return true;\n    }\n}\n\n/**\n * @title The Compound Faucet Test Token\n * @author Compound\n * @notice A simple test token that lets anyone get more of it.\n */\ncontract NonStandardFaucetToken is NonStandardToken {\n    constructor(uint256 _initialAmount, string memory _tokenName, uint8 _decimalUnits, string memory _tokenSymbol)\n        NonStandardToken(_initialAmount, _tokenName, _decimalUnits, _tokenSymbol) {\n    }\n\n    function allocateTo(address _owner, uint256 value) public {\n        balanceOf[_owner] += value;\n        totalSupply += value;\n        emit Transfer(address(this), _owner, value);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10**64) {\n                value /= 10**64;\n                result += 64;\n            }\n            if (value >= 10**32) {\n                value /= 10**32;\n                result += 32;\n            }\n            if (value >= 10**16) {\n                value /= 10**16;\n                result += 16;\n            }\n            if (value >= 10**8) {\n                value /= 10**8;\n                result += 8;\n            }\n            if (value >= 10**4) {\n                value /= 10**4;\n                result += 4;\n            }\n            if (value >= 10**2) {\n                value /= 10**2;\n                result += 2;\n            }\n            if (value >= 10**1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n        }\n    }\n}\n"},{"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/CometInterface.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometMainInterface.sol\";\nimport \"./CometExtInterface.sol\";\n\n/**\n * @title Compound's Comet Interface\n * @notice An efficient monolithic money market protocol\n * @author Compound\n */\nabstract contract CometInterface is CometMainInterface, CometExtInterface {}\n"},{"file_path":"contracts/test/MockRedstoneOracle.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\n\n/**\n * @title Mock oracle\n * @notice Mock oracle to test the scaling price feed with updated update time\n * @author Compound\n */\ncontract MockRedstoneOracle {\n\n    /// @notice Number of decimals for returned prices\n    uint8 public immutable decimals;\n\n    /// @notice Underlying Chainlink price feed where prices are fetched from\n    address public immutable underlyingPriceFeed;\n    uint256 public immutable lastPrice;\n\n    /**\n     * @notice Construct a new scaling price feed\n     * @param underlyingPriceFeed_ The address of the underlying price feed to fetch prices from\n     **/\n    constructor(address underlyingPriceFeed_, uint256 lastPrice_) {\n        underlyingPriceFeed = underlyingPriceFeed_;\n        decimals = AggregatorV3Interface(underlyingPriceFeed_).decimals();\n        lastPrice = lastPrice_;\n    }\n\n\n    /**\n     * @notice Price for the latest round\n     * @return roundId Round id from the underlying price feed\n     * @return answer Latest price for the asset in terms of ETH\n     * @return startedAt Timestamp when the round was started; passed on from underlying price feed\n     * @return updatedAt Current timestamp\n     * @return answeredInRound Round id in which the answer was computed; passed on from underlying price feed\n     **/\n    function latestRoundData() external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    ) {\n        return (1, int256(lastPrice), block.timestamp, block.timestamp, 1);\n    }\n}\n"},{"file_path":"contracts/vendor/proxy/Proxy.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n    /**\n     * @dev Delegates the current call to `implementation`.\n     *\n     * This function does not return to its internal call site, it will return directly to the external caller.\n     */\n    function _delegate(address implementation) internal virtual {\n        assembly {\n            // Copy msg.data. We take full control of memory in this inline assembly\n            // block because it will not return to Solidity code. We overwrite the\n            // Solidity scratch pad at memory position 0.\n            calldatacopy(0, 0, calldatasize())\n\n            // Call the implementation.\n            // out and outsize are 0 because we don't know the size yet.\n            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n            // Copy the returned data.\n            returndatacopy(0, 0, returndatasize())\n\n            switch result\n            // delegatecall returns 0 on error.\n            case 0 {\n                revert(0, returndatasize())\n            }\n            default {\n                return(0, returndatasize())\n            }\n        }\n    }\n\n    /**\n     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n     * and {_fallback} should delegate.\n     */\n    function _implementation() internal view virtual returns (address);\n\n    /**\n     * @dev Delegates the current call to the address returned by `_implementation()`.\n     *\n     * This function does not return to its internall call site, it will return directly to the external caller.\n     */\n    function _fallback() internal virtual {\n        _beforeFallback();\n        _delegate(_implementation());\n    }\n\n    /**\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n     * function in the contract matches the call data.\n     */\n    fallback() external payable virtual {\n        _fallback();\n    }\n\n    /**\n     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n     * is empty.\n     */\n    receive() external payable virtual {\n        _fallback();\n    }\n\n    /**\n     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n     * call, or as part of the Solidity `fallback` or `receive` functions.\n     *\n     * If overriden should call `super._beforeFallback()`.\n     */\n    function _beforeFallback() internal virtual {}\n}\n"},{"file_path":"contracts/Comet.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometMainInterface.sol\";\nimport \"./IERC20NonStandard.sol\";\nimport \"./IPriceFeed.sol\";\n\n/**\n * @title Compound's Comet Contract\n * @notice An efficient monolithic money market protocol\n * @author Compound\n */\ncontract Comet 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    /** Collateral asset configuration (packed) **/\n\n    uint256 internal immutable asset00_a;\n    uint256 internal immutable asset00_b;\n    uint256 internal immutable asset01_a;\n    uint256 internal immutable asset01_b;\n    uint256 internal immutable asset02_a;\n    uint256 internal immutable asset02_b;\n    uint256 internal immutable asset03_a;\n    uint256 internal immutable asset03_b;\n    uint256 internal immutable asset04_a;\n    uint256 internal immutable asset04_b;\n    uint256 internal immutable asset05_a;\n    uint256 internal immutable asset05_b;\n    uint256 internal immutable asset06_a;\n    uint256 internal immutable asset06_b;\n    uint256 internal immutable asset07_a;\n    uint256 internal immutable asset07_b;\n    uint256 internal immutable asset08_a;\n    uint256 internal immutable asset08_b;\n    uint256 internal immutable asset09_a;\n    uint256 internal immutable asset09_b;\n    uint256 internal immutable asset10_a;\n    uint256 internal immutable asset10_b;\n    uint256 internal immutable asset11_a;\n    uint256 internal immutable asset11_b;\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) 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        (asset00_a, asset00_b) = getPackedAssetInternal(config.assetConfigs, 0);\n        (asset01_a, asset01_b) = getPackedAssetInternal(config.assetConfigs, 1);\n        (asset02_a, asset02_b) = getPackedAssetInternal(config.assetConfigs, 2);\n        (asset03_a, asset03_b) = getPackedAssetInternal(config.assetConfigs, 3);\n        (asset04_a, asset04_b) = getPackedAssetInternal(config.assetConfigs, 4);\n        (asset05_a, asset05_b) = getPackedAssetInternal(config.assetConfigs, 5);\n        (asset06_a, asset06_b) = getPackedAssetInternal(config.assetConfigs, 6);\n        (asset07_a, asset07_b) = getPackedAssetInternal(config.assetConfigs, 7);\n        (asset08_a, asset08_b) = getPackedAssetInternal(config.assetConfigs, 8);\n        (asset09_a, asset09_b) = getPackedAssetInternal(config.assetConfigs, 9);\n        (asset10_a, asset10_b) = getPackedAssetInternal(config.assetConfigs, 10);\n        (asset11_a, asset11_b) = getPackedAssetInternal(config.assetConfigs, 11);\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     * @dev Checks and gets the packed asset info for storage\n     */\n    function getPackedAssetInternal(AssetConfig[] memory assetConfigs, uint i) internal view returns (uint256, uint256) {\n        AssetConfig memory assetConfig;\n        if (i < assetConfigs.length) {\n            assembly {\n                assetConfig := mload(add(add(assetConfigs, 0x20), mul(i, 0x20)))\n            }\n        } else {\n            return (0, 0);\n        }\n        address asset = assetConfig.asset;\n        address priceFeed = assetConfig.priceFeed;\n        uint8 decimals_ = assetConfig.decimals;\n\n        // Short-circuit if asset is nil\n        if (asset == address(0)) {\n            return (0, 0);\n        }\n\n        // Sanity check price feed and asset decimals\n        if (IPriceFeed(priceFeed).decimals() != PRICE_FEED_DECIMALS) revert BadDecimals();\n        if (IERC20NonStandard(asset).decimals() != decimals_) revert BadDecimals();\n\n        // Ensure collateral factors are within range\n        if (assetConfig.borrowCollateralFactor >= assetConfig.liquidateCollateralFactor) revert BorrowCFTooLarge();\n        if (assetConfig.liquidateCollateralFactor > MAX_COLLATERAL_FACTOR) revert LiquidateCFTooLarge();\n\n        unchecked {\n            // Keep 4 decimals for each factor\n            uint64 descale = FACTOR_SCALE / 1e4;\n            uint16 borrowCollateralFactor = uint16(assetConfig.borrowCollateralFactor / descale);\n            uint16 liquidateCollateralFactor = uint16(assetConfig.liquidateCollateralFactor / descale);\n            uint16 liquidationFactor = uint16(assetConfig.liquidationFactor / descale);\n\n            // Be nice and check descaled values are still within range\n            if (borrowCollateralFactor >= liquidateCollateralFactor) revert BorrowCFTooLarge();\n\n            // Keep whole units of asset for supply cap\n            uint64 supplyCap = uint64(assetConfig.supplyCap / (10 ** decimals_));\n\n            uint256 word_a = (uint160(asset) << 0 |\n                              uint256(borrowCollateralFactor) << 160 |\n                              uint256(liquidateCollateralFactor) << 176 |\n                              uint256(liquidationFactor) << 192);\n            uint256 word_b = (uint160(priceFeed) << 0 |\n                              uint256(decimals_) << 160 |\n                              uint256(supplyCap) << 168);\n\n            return (word_a, word_b);\n        }\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        if (i >= numAssets) revert BadAsset();\n\n        uint256 word_a;\n        uint256 word_b;\n\n        if (i == 0) {\n            word_a = asset00_a;\n            word_b = asset00_b;\n        } else if (i == 1) {\n            word_a = asset01_a;\n            word_b = asset01_b;\n        } else if (i == 2) {\n            word_a = asset02_a;\n            word_b = asset02_b;\n        } else if (i == 3) {\n            word_a = asset03_a;\n            word_b = asset03_b;\n        } else if (i == 4) {\n            word_a = asset04_a;\n            word_b = asset04_b;\n        } else if (i == 5) {\n            word_a = asset05_a;\n            word_b = asset05_b;\n        } else if (i == 6) {\n            word_a = asset06_a;\n            word_b = asset06_b;\n        } else if (i == 7) {\n            word_a = asset07_a;\n            word_b = asset07_b;\n        } else if (i == 8) {\n            word_a = asset08_a;\n            word_b = asset08_b;\n        } else if (i == 9) {\n            word_a = asset09_a;\n            word_b = asset09_b;\n        } else if (i == 10) {\n            word_a = asset10_a;\n            word_b = asset10_b;\n        } else if (i == 11) {\n            word_a = asset11_a;\n            word_b = asset11_b;\n        } else {\n            revert Absurd();\n        }\n\n        address asset = address(uint160(word_a & type(uint160).max));\n        uint64 rescale = FACTOR_SCALE / 1e4;\n        uint64 borrowCollateralFactor = uint64(((word_a >> 160) & type(uint16).max) * rescale);\n        uint64 liquidateCollateralFactor = uint64(((word_a >> 176) & type(uint16).max) * rescale);\n        uint64 liquidationFactor = uint64(((word_a >> 192) & type(uint16).max) * rescale);\n\n        address priceFeed = address(uint160(word_b & type(uint160).max));\n        uint8 decimals_ = uint8(((word_b >> 160) & type(uint8).max));\n        uint64 scale = uint64(10 ** decimals_);\n        uint128 supplyCap = uint128(((word_b >> 168) & type(uint64).max) * scale);\n\n        return AssetInfo({\n            offset: i,\n            asset: asset,\n            priceFeed: priceFeed,\n            scale: scale,\n            borrowCollateralFactor: borrowCollateralFactor,\n            liquidateCollateralFactor: liquidateCollateralFactor,\n            liquidationFactor: liquidationFactor,\n            supplyCap: supplyCap\n         });\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        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     * @notice Accrue interest and rewards for an account\n     **/\n    function accrueAccount(address account) override external {\n        accrueInternal();\n\n        UserBasic memory basic = userBasic[account];\n        updateBasePrincipal(account, basic, basic.principal);\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        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        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        int liquidity = signedMulPrice(\n            presentValue(principal),\n            getPrice(baseTokenPriceFeed),\n            uint64(baseScale)\n        );\n\n        for (uint8 i = 0; i < numAssets; ) {\n            if (isInAsset(assetsIn, i)) {\n                if (liquidity >= 0) {\n                    return true;\n                }\n\n                AssetInfo memory asset = getAssetInfo(i);\n                uint 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            unchecked { i++; }\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    function isLiquidatable(address account) override public view returns (bool) {\n        int104 principal = userBasic[account].principal;\n\n        if (principal >= 0) {\n            return false;\n        }\n\n        uint16 assetsIn = userBasic[account].assetsIn;\n        int liquidity = signedMulPrice(\n            presentValue(principal),\n            getPrice(baseTokenPriceFeed),\n            uint64(baseScale)\n        );\n\n        for (uint8 i = 0; i < numAssets; ) {\n            if (isInAsset(assetsIn, i)) {\n                if (liquidity >= 0) {\n                    return false;\n                }\n\n                AssetInfo memory asset = getAssetInfo(i);\n                uint newAmount = mulPrice(\n                    userCollateral[account][asset.asset].balance,\n                    getPrice(asset.priceFeed),\n                    asset.scale\n                );\n                liquidity += signed256(mulFactor(\n                    newAmount,\n                    asset.liquidateCollateralFactor\n                ));\n            }\n            unchecked { i++; }\n        }\n\n        return liquidity < 0;\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     * @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     */\n    function isInAsset(uint16 assetsIn, uint8 assetOffset) internal pure returns (bool) {\n        return (assetsIn & (uint16(1) << assetOffset) != 0);\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            userBasic[account].assetsIn |= (uint16(1) << assetInfo.offset);\n        } else if (initialUserBalance != 0 && finalUserBalance == 0) {\n            // clear bit for asset\n            userBasic[account].assetsIn &= ~(uint16(1) << assetInfo.offset);\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, 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, 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(msg.sender, 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 operator, address from, address dst, address asset, uint amount) internal nonReentrant {\n        if (isSupplyPaused()) revert Paused();\n        if (!hasPermission(from, operator)) revert Unauthorized();\n\n        if (asset == baseToken) {\n            if (amount == type(uint256).max) {\n                amount = borrowBalanceOf(dst);\n            }\n            return supplyBase(from, dst, amount);\n        } else {\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\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        amount = safe128(doTransferIn(asset, from, amount));\n\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\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            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 (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall();\n            if (!isBorrowCollateralized(src)) revert NotCollateralized();\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        updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew);\n        updateAssetsIn(dst, assetInfo, dstCollateral, dstCollateralNew);\n\n        // Note: no accrue interest, BorrowCF < LiquidationCF covers small changes\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            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 (uint256(-srcBalance) < baseBorrowMin) revert BorrowTooSmall();\n            if (!isBorrowCollateralized(src)) revert NotCollateralized();\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    function withdrawCollateral(address src, address to, address asset, uint128 amount) internal {\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        updateAssetsIn(src, assetInfo, srcCollateral, srcCollateralNew);\n\n        // Note: no accrue interest, BorrowCF < LiquidationCF covers small changes\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    function absorbInternal(address absorber, address account) internal {\n        if (!isLiquidatable(account)) 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\n        uint256 basePrice = getPrice(baseTokenPriceFeed);\n        uint256 deltaValue = 0;\n\n        for (uint8 i = 0; i < numAssets; ) {\n            if (isInAsset(assetsIn, i)) {\n                AssetInfo memory assetInfo = getAssetInfo(i);\n                address asset = assetInfo.asset;\n                uint128 seizeAmount = userCollateral[account][asset].balance;\n                userCollateral[account][asset].balance = 0;\n                totalsCollateral[asset].totalSupplyAsset -= seizeAmount;\n\n                uint256 value = mulPrice(seizeAmount, getPrice(assetInfo.priceFeed), 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\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        uint256 assetPrice = getPrice(assetInfo.priceFeed);\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        uint256 assetPriceDiscounted = mulFactor(assetPrice, FACTOR_SCALE - discountFactor);\n        uint256 basePrice = getPrice(baseTokenPriceFeed);\n        // # of collateral assets\n        // = (TotalValueOfBaseAmount / DiscountedPriceOfCollateralAsset) * assetScale\n        // = ((basePrice * baseAmount / baseScale) / assetPriceDiscounted) * 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}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolActions.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Permissionless pool actions\n/// @notice Contains pool methods that can be called by anyone\ninterface IUniswapV3PoolActions {\n    /// @notice Sets the initial price for the pool\n    /// @dev Price is represented as a sqrt(amountToken1/amountToken0) Q64.96 value\n    /// @param sqrtPriceX96 the initial sqrt price of the pool as a Q64.96\n    function initialize(uint160 sqrtPriceX96) external;\n\n    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback\n    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends\n    /// on tickLower, tickUpper, the amount of liquidity, and the current price.\n    /// @param recipient The address for which the liquidity will be created\n    /// @param tickLower The lower tick of the position in which to add liquidity\n    /// @param tickUpper The upper tick of the position in which to add liquidity\n    /// @param amount The amount of liquidity to mint\n    /// @param data Any data that should be passed through to the callback\n    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback\n    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback\n    function mint(\n        address recipient,\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount,\n        bytes calldata data\n    ) external returns (uint256 amount0, uint256 amount1);\n\n    /// @notice Collects tokens owed to a position\n    /// @dev Does not recompute fees earned, which must be done either via mint or burn of any amount of liquidity.\n    /// Collect must be called by the position owner. To withdraw only token0 or only token1, amount0Requested or\n    /// amount1Requested may be set to zero. To withdraw all tokens owed, caller may pass any value greater than the\n    /// actual tokens owed, e.g. type(uint128).max. Tokens owed may be from accumulated swap fees or burned liquidity.\n    /// @param recipient The address which should receive the fees collected\n    /// @param tickLower The lower tick of the position for which to collect fees\n    /// @param tickUpper The upper tick of the position for which to collect fees\n    /// @param amount0Requested How much token0 should be withdrawn from the fees owed\n    /// @param amount1Requested How much token1 should be withdrawn from the fees owed\n    /// @return amount0 The amount of fees collected in token0\n    /// @return amount1 The amount of fees collected in token1\n    function collect(\n        address recipient,\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount0Requested,\n        uint128 amount1Requested\n    ) external returns (uint128 amount0, uint128 amount1);\n\n    /// @notice Burn liquidity from the sender and account tokens owed for the liquidity to the position\n    /// @dev Can be used to trigger a recalculation of fees owed to a position by calling with an amount of 0\n    /// @dev Fees must be collected separately via a call to #collect\n    /// @param tickLower The lower tick of the position for which to burn liquidity\n    /// @param tickUpper The upper tick of the position for which to burn liquidity\n    /// @param amount How much liquidity to burn\n    /// @return amount0 The amount of token0 sent to the recipient\n    /// @return amount1 The amount of token1 sent to the recipient\n    function burn(\n        int24 tickLower,\n        int24 tickUpper,\n        uint128 amount\n    ) external returns (uint256 amount0, uint256 amount1);\n\n    /// @notice Swap token0 for token1, or token1 for token0\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3SwapCallback#uniswapV3SwapCallback\n    /// @param recipient The address to receive the output of the swap\n    /// @param zeroForOne The direction of the swap, true for token0 to token1, false for token1 to token0\n    /// @param amountSpecified The amount of the swap, which implicitly configures the swap as exact input (positive), or exact output (negative)\n    /// @param sqrtPriceLimitX96 The Q64.96 sqrt price limit. If zero for one, the price cannot be less than this\n    /// value after the swap. If one for zero, the price cannot be greater than this value after the swap\n    /// @param data Any data to be passed through to the callback\n    /// @return amount0 The delta of the balance of token0 of the pool, exact when negative, minimum when positive\n    /// @return amount1 The delta of the balance of token1 of the pool, exact when negative, minimum when positive\n    function swap(\n        address recipient,\n        bool zeroForOne,\n        int256 amountSpecified,\n        uint160 sqrtPriceLimitX96,\n        bytes calldata data\n    ) external returns (int256 amount0, int256 amount1);\n\n    /// @notice Receive token0 and/or token1 and pay it back, plus a fee, in the callback\n    /// @dev The caller of this method receives a callback in the form of IUniswapV3FlashCallback#uniswapV3FlashCallback\n    /// @dev Can be used to donate underlying tokens pro-rata to currently in-range liquidity providers by calling\n    /// with 0 amount{0,1} and sending the donation amount(s) from the callback\n    /// @param recipient The address which will receive the token0 and token1 amounts\n    /// @param amount0 The amount of token0 to send\n    /// @param amount1 The amount of token1 to send\n    /// @param data Any data to be passed through to the callback\n    function flash(\n        address recipient,\n        uint256 amount0,\n        uint256 amount1,\n        bytes calldata data\n    ) external;\n\n    /// @notice Increase the maximum number of price and liquidity observations that this pool will store\n    /// @dev This method is no-op if the pool already has an observationCardinalityNext greater than or equal to\n    /// the input observationCardinalityNext.\n    /// @param observationCardinalityNext The desired minimum number of observations for the pool to store\n    function increaseObservationCardinalityNext(uint16 observationCardinalityNext) external;\n}\n"},{"file_path":"contracts/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.15;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}"},{"file_path":"contracts/vendor/canonical-weth/contracts/WETH9.sol","source_code":"/**\n *Submitted for verification at Etherscan.io on 2017-12-12\n*/\n\n// Copyright (C) 2015, 2016, 2017 Dapphub\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity 0.8.15;\n\ncontract WETH9 {\n    string public name     = \"Wrapped Ether\";\n    string public symbol   = \"WETH\";\n    uint8  public decimals = 18;\n\n    event  Approval(address indexed src, address indexed guy, uint wad);\n    event  Transfer(address indexed src, address indexed dst, uint wad);\n    event  Deposit(address indexed dst, uint wad);\n    event  Withdrawal(address indexed src, uint wad);\n\n    mapping (address => uint)                       public  balanceOf;\n    mapping (address => mapping (address => uint))  public  allowance;\n\n    receive() external payable {\n        deposit();\n    }\n    function deposit() public payable {\n        balanceOf[msg.sender] += msg.value;\n        emit Deposit(msg.sender, msg.value);\n    }\n    function withdraw(uint wad) public {\n        require(balanceOf[msg.sender] >= wad);\n        balanceOf[msg.sender] -= wad;\n        payable(msg.sender).transfer(wad);\n        emit Withdrawal(msg.sender, wad);\n    }\n\n    function totalSupply() public view returns (uint) {\n        return address(this).balance;\n    }\n\n    function approve(address guy, uint wad) public returns (bool) {\n        allowance[msg.sender][guy] = wad;\n        emit Approval(msg.sender, guy, wad);\n        return true;\n    }\n\n    function transfer(address dst, uint wad) public returns (bool) {\n        return transferFrom(msg.sender, dst, wad);\n    }\n\n    function transferFrom(address src, address dst, uint wad)\n        public\n        returns (bool)\n    {\n        require(balanceOf[src] >= wad);\n\n        if (src != msg.sender && allowance[src][msg.sender] != type(uint).max) {\n            require(allowance[src][msg.sender] >= wad);\n            allowance[src][msg.sender] -= wad;\n        }\n\n        balanceOf[src] -= wad;\n        balanceOf[dst] += wad;\n\n        emit Transfer(src, dst, wad);\n\n        return true;\n    }\n}\n\n\n/*\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n\n*/"},{"file_path":"contracts/Configurator.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometFactory.sol\";\nimport \"./CometConfiguration.sol\";\nimport \"./ConfiguratorStorage.sol\";\nimport \"./marketupdates/MarketAdminPermissionCheckerInterface.sol\";\n\ncontract Configurator is ConfiguratorStorage {\n\n    /** Custom events **/\n    event AddAsset(address indexed cometProxy, AssetConfig assetConfig);\n    event CometDeployed(address indexed cometProxy, address indexed newComet);\n    event GovernorTransferred(address indexed oldGovernor, address indexed newGovernor);\n    event SetFactory(address indexed cometProxy, address indexed oldFactory, address indexed newFactory);\n    event SetGovernor(address indexed cometProxy, address indexed oldGovernor, address indexed newGovernor);\n    event SetConfiguration(address indexed cometProxy, Configuration oldConfiguration, Configuration newConfiguration);\n    event SetPauseGuardian(address indexed cometProxy, address indexed oldPauseGuardian, address indexed newPauseGuardian);\n    event SetMarketAdminPermissionChecker(address indexed oldMarketAdminPermissionChecker, address indexed newMarketAdminPermissionChecker);\n    event SetBaseTokenPriceFeed(address indexed cometProxy, address indexed oldBaseTokenPriceFeed, address indexed newBaseTokenPriceFeed);\n    event SetExtensionDelegate(address indexed cometProxy, address indexed oldExt, address indexed newExt);\n    event SetSupplyKink(address indexed cometProxy,uint64 oldKink, uint64 newKink);\n    event SetSupplyPerYearInterestRateSlopeLow(address indexed cometProxy,uint64 oldIRSlopeLow, uint64 newIRSlopeLow);\n    event SetSupplyPerYearInterestRateSlopeHigh(address indexed cometProxy,uint64 oldIRSlopeHigh, uint64 newIRSlopeHigh);\n    event SetSupplyPerYearInterestRateBase(address indexed cometProxy,uint64 oldIRBase, uint64 newIRBase);\n    event SetBorrowKink(address indexed cometProxy,uint64 oldKink, uint64 newKink);\n    event SetBorrowPerYearInterestRateSlopeLow(address indexed cometProxy,uint64 oldIRSlopeLow, uint64 newIRSlopeLow);\n    event SetBorrowPerYearInterestRateSlopeHigh(address indexed cometProxy,uint64 oldIRSlopeHigh, uint64 newIRSlopeHigh);\n    event SetBorrowPerYearInterestRateBase(address indexed cometProxy,uint64 oldIRBase, uint64 newIRBase);\n    event SetStoreFrontPriceFactor(address indexed cometProxy, uint64 oldStoreFrontPriceFactor, uint64 newStoreFrontPriceFactor);\n    event SetBaseTrackingSupplySpeed(address indexed cometProxy, uint64 oldBaseTrackingSupplySpeed, uint64 newBaseTrackingSupplySpeed);\n    event SetBaseTrackingBorrowSpeed(address indexed cometProxy, uint64 oldBaseTrackingBorrowSpeed, uint64 newBaseTrackingBorrowSpeed);\n    event SetBaseMinForRewards(address indexed cometProxy, uint104 oldBaseMinForRewards, uint104 newBaseMinForRewards);\n    event SetBaseBorrowMin(address indexed cometProxy, uint104 oldBaseBorrowMin, uint104 newBaseBorrowMin);\n    event SetTargetReserves(address indexed cometProxy, uint104 oldTargetReserves, uint104 newTargetReserves);\n    event UpdateAsset(address indexed cometProxy, AssetConfig oldAssetConfig, AssetConfig newAssetConfig);\n    event UpdateAssetPriceFeed(address indexed cometProxy, address indexed asset, address oldPriceFeed, address newPriceFeed);\n    event UpdateAssetBorrowCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldBorrowCF, uint64 newBorrowCF);\n    event UpdateAssetLiquidateCollateralFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidateCF, uint64 newLiquidateCF);\n    event UpdateAssetLiquidationFactor(address indexed cometProxy, address indexed asset, uint64 oldLiquidationFactor, uint64 newLiquidationFactor);\n    event UpdateAssetSupplyCap(address indexed cometProxy, address indexed asset, uint128 oldSupplyCap, uint128 newSupplyCap);\n\n    /** Custom errors **/\n    error AlreadyInitialized();\n    error AssetDoesNotExist();\n    error ConfigurationAlreadyExists();\n    error InvalidAddress();\n    error Unauthorized();\n\n    /**\n     * @notice Constructs a new Configurator instance\n     **/\n    constructor() {\n        // Set a high version to prevent the implementation contract from being initialized\n        version = type(uint256).max;\n    }\n\n    /**\n     * @dev Ensures that the caller is either the governor or the market admin.\n     * This delegates the permission check logic to the MarketAdminPermissionChecker contract.\n     */\n    modifier governorOrMarketAdmin {\n        if(msg.sender != governor) marketAdminPermissionChecker.checkUpdatePermission(msg.sender);\n        _;\n    }\n\n    /**\n     * @notice Initializes the storage for Configurator\n     * @param governor_ The address of the governor\n     **/\n    function initialize(address governor_) public {\n        if (version != 0) revert AlreadyInitialized();\n        if (governor_ == address(0)) revert InvalidAddress();\n\n        governor = governor_;\n        version = 1;\n    }\n\n    /**\n     * @notice Sets the factory for a Comet proxy\n     * @dev Note: Only callable by governor\n     **/\n    function setFactory(address cometProxy, address newFactory) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldFactory = factory[cometProxy];\n        factory[cometProxy] = newFactory;\n        emit SetFactory(cometProxy, oldFactory, newFactory);\n    }\n\n    /**\n     * @notice Sets the entire Configuration for a Comet proxy\n     * @dev Note: All params can later be updated by the governor except for `baseToken` and `trackingIndexScale`\n     **/\n    function setConfiguration(address cometProxy, Configuration calldata newConfiguration) external {\n        if (msg.sender != governor) revert Unauthorized();\n        Configuration memory oldConfiguration = configuratorParams[cometProxy];\n        if (oldConfiguration.baseToken != address(0) &&\n            (oldConfiguration.baseToken != newConfiguration.baseToken ||\n             oldConfiguration.trackingIndexScale != newConfiguration.trackingIndexScale))\n            revert ConfigurationAlreadyExists();\n\n        configuratorParams[cometProxy] = newConfiguration;\n        emit SetConfiguration(cometProxy, oldConfiguration, newConfiguration);\n    }\n\n    /** Governance setters for Comet-related configuration **/\n\n    function setGovernor(address cometProxy, address newGovernor) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldGovernor = configuratorParams[cometProxy].governor;\n        configuratorParams[cometProxy].governor = newGovernor;\n        emit SetGovernor(cometProxy, oldGovernor, newGovernor);\n    }\n\n    function setPauseGuardian(address cometProxy, address newPauseGuardian) external {\n        if (msg.sender != governor) revert Unauthorized();\n        address oldPauseGuardian = configuratorParams[cometProxy].pauseGuardian;\n        configuratorParams[cometProxy].pauseGuardian = newPauseGuardian;\n        emit SetPauseGuardian(cometProxy, oldPauseGuardian, newPauseGuardian);\n    }\n\n    /**\n    * @notice Sets the MarketAdminPermissionChecker contract\n    * @dev Note: Only callable by governor\n    **/\n    function setMarketAdminPermissionChecker(MarketAdminPermissionCheckerInterface newMarketAdminPermissionChecker) external {\n        if (msg.sender != governor) revert Unauthorized();\n        address oldMarketAdminPermissionChecker = address(marketAdminPermissionChecker);\n        marketAdminPermissionChecker = newMarketAdminPermissionChecker;\n        emit SetMarketAdminPermissionChecker(oldMarketAdminPermissionChecker, address(newMarketAdminPermissionChecker));\n    }\n\n    function setBaseTokenPriceFeed(address cometProxy, address newBaseTokenPriceFeed) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldBaseTokenPriceFeed = configuratorParams[cometProxy].baseTokenPriceFeed;\n        configuratorParams[cometProxy].baseTokenPriceFeed = newBaseTokenPriceFeed;\n        emit SetBaseTokenPriceFeed(cometProxy, oldBaseTokenPriceFeed, newBaseTokenPriceFeed);\n    }\n\n    function setExtensionDelegate(address cometProxy, address newExtensionDelegate) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        address oldExtensionDelegate = configuratorParams[cometProxy].extensionDelegate;\n        configuratorParams[cometProxy].extensionDelegate = newExtensionDelegate;\n        emit SetExtensionDelegate(cometProxy, oldExtensionDelegate, newExtensionDelegate);\n    }\n\n    function setSupplyKink(address cometProxy, uint64 newSupplyKink) external governorOrMarketAdmin {\n        uint64 oldSupplyKink = configuratorParams[cometProxy].supplyKink;\n        configuratorParams[cometProxy].supplyKink = newSupplyKink;\n        emit SetSupplyKink(cometProxy, oldSupplyKink, newSupplyKink);\n    }\n\n    function setSupplyPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external governorOrMarketAdmin {\n        uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow;\n        configuratorParams[cometProxy].supplyPerYearInterestRateSlopeLow = newSlope;\n        emit SetSupplyPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope);\n    }\n\n    function setSupplyPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external governorOrMarketAdmin {\n        uint64 oldSlope = configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh;\n        configuratorParams[cometProxy].supplyPerYearInterestRateSlopeHigh = newSlope;\n        emit SetSupplyPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope);\n    }\n\n    function setSupplyPerYearInterestRateBase(address cometProxy, uint64 newBase) external governorOrMarketAdmin {\n        uint64 oldBase = configuratorParams[cometProxy].supplyPerYearInterestRateBase;\n        configuratorParams[cometProxy].supplyPerYearInterestRateBase = newBase;\n        emit SetSupplyPerYearInterestRateBase(cometProxy, oldBase, newBase);\n    }\n\n    function setBorrowKink(address cometProxy, uint64 newBorrowKink) external governorOrMarketAdmin {\n        uint64 oldBorrowKink = configuratorParams[cometProxy].borrowKink;\n        configuratorParams[cometProxy].borrowKink = newBorrowKink;\n        emit SetBorrowKink(cometProxy, oldBorrowKink, newBorrowKink);\n    }\n\n    function setBorrowPerYearInterestRateSlopeLow(address cometProxy, uint64 newSlope) external governorOrMarketAdmin {\n        uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow;\n        configuratorParams[cometProxy].borrowPerYearInterestRateSlopeLow = newSlope;\n        emit SetBorrowPerYearInterestRateSlopeLow(cometProxy, oldSlope, newSlope);\n    }\n\n    function setBorrowPerYearInterestRateSlopeHigh(address cometProxy, uint64 newSlope) external governorOrMarketAdmin {\n        uint64 oldSlope = configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh;\n        configuratorParams[cometProxy].borrowPerYearInterestRateSlopeHigh = newSlope;\n        emit SetBorrowPerYearInterestRateSlopeHigh(cometProxy, oldSlope, newSlope);\n    }\n\n    function setBorrowPerYearInterestRateBase(address cometProxy, uint64 newBase) external governorOrMarketAdmin {\n        uint64 oldBase = configuratorParams[cometProxy].borrowPerYearInterestRateBase;\n        configuratorParams[cometProxy].borrowPerYearInterestRateBase = newBase;\n        emit SetBorrowPerYearInterestRateBase(cometProxy, oldBase, newBase);\n    }\n\n    function setStoreFrontPriceFactor(address cometProxy, uint64 newStoreFrontPriceFactor) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint64 oldStoreFrontPriceFactor = configuratorParams[cometProxy].storeFrontPriceFactor;\n        configuratorParams[cometProxy].storeFrontPriceFactor = newStoreFrontPriceFactor;\n        emit SetStoreFrontPriceFactor(cometProxy, oldStoreFrontPriceFactor, newStoreFrontPriceFactor);\n    }\n\n    function setBaseTrackingSupplySpeed(address cometProxy, uint64 newBaseTrackingSupplySpeed) external governorOrMarketAdmin {\n        uint64 oldBaseTrackingSupplySpeed = configuratorParams[cometProxy].baseTrackingSupplySpeed;\n        configuratorParams[cometProxy].baseTrackingSupplySpeed = newBaseTrackingSupplySpeed;\n        emit SetBaseTrackingSupplySpeed(cometProxy, oldBaseTrackingSupplySpeed, newBaseTrackingSupplySpeed);\n    }\n\n    function setBaseTrackingBorrowSpeed(address cometProxy, uint64 newBaseTrackingBorrowSpeed) external governorOrMarketAdmin {\n        uint64 oldBaseTrackingBorrowSpeed = configuratorParams[cometProxy].baseTrackingBorrowSpeed;\n        configuratorParams[cometProxy].baseTrackingBorrowSpeed = newBaseTrackingBorrowSpeed;\n        emit SetBaseTrackingBorrowSpeed(cometProxy, oldBaseTrackingBorrowSpeed, newBaseTrackingBorrowSpeed);\n    }\n\n    function setBaseMinForRewards(address cometProxy, uint104 newBaseMinForRewards) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint104 oldBaseMinForRewards = configuratorParams[cometProxy].baseMinForRewards;\n        configuratorParams[cometProxy].baseMinForRewards = newBaseMinForRewards;\n        emit SetBaseMinForRewards(cometProxy, oldBaseMinForRewards, newBaseMinForRewards);\n    }\n\n    function setBaseBorrowMin(address cometProxy, uint104 newBaseBorrowMin) external governorOrMarketAdmin {\n        uint104 oldBaseBorrowMin = configuratorParams[cometProxy].baseBorrowMin;\n        configuratorParams[cometProxy].baseBorrowMin = newBaseBorrowMin;\n        emit SetBaseBorrowMin(cometProxy, oldBaseBorrowMin, newBaseBorrowMin);\n    }\n\n    function setTargetReserves(address cometProxy, uint104 newTargetReserves) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint104 oldTargetReserves = configuratorParams[cometProxy].targetReserves;\n        configuratorParams[cometProxy].targetReserves = newTargetReserves;\n        emit SetTargetReserves(cometProxy, oldTargetReserves, newTargetReserves);\n    }\n\n    function addAsset(address cometProxy, AssetConfig calldata assetConfig) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        configuratorParams[cometProxy].assetConfigs.push(assetConfig);\n        emit AddAsset(cometProxy, assetConfig);\n    }\n\n    function updateAsset(address cometProxy, AssetConfig calldata newAssetConfig) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint assetIndex = getAssetIndex(cometProxy, newAssetConfig.asset);\n        AssetConfig memory oldAssetConfig = configuratorParams[cometProxy].assetConfigs[assetIndex];\n        configuratorParams[cometProxy].assetConfigs[assetIndex] = newAssetConfig;\n        emit UpdateAsset(cometProxy, oldAssetConfig, newAssetConfig);\n    }\n\n    function updateAssetPriceFeed(address cometProxy, address asset, address newPriceFeed) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        address oldPriceFeed = configuratorParams[cometProxy].assetConfigs[assetIndex].priceFeed;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].priceFeed = newPriceFeed;\n        emit UpdateAssetPriceFeed(cometProxy, asset, oldPriceFeed, newPriceFeed);\n    }\n\n    function updateAssetBorrowCollateralFactor(address cometProxy, address asset, uint64 newBorrowCF) external governorOrMarketAdmin {\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        uint64 oldBorrowCF = configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].borrowCollateralFactor = newBorrowCF;\n        emit UpdateAssetBorrowCollateralFactor(cometProxy, asset, oldBorrowCF, newBorrowCF);\n    }\n\n    function updateAssetLiquidateCollateralFactor(address cometProxy, address asset, uint64 newLiquidateCF) external governorOrMarketAdmin {\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        uint64 oldLiquidateCF = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].liquidateCollateralFactor = newLiquidateCF;\n        emit UpdateAssetLiquidateCollateralFactor(cometProxy, asset, oldLiquidateCF, newLiquidateCF);\n    }\n\n    function updateAssetLiquidationFactor(address cometProxy, address asset, uint64 newLiquidationFactor) external governorOrMarketAdmin {\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        uint64 oldLiquidationFactor = configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].liquidationFactor = newLiquidationFactor;\n        emit UpdateAssetLiquidationFactor(cometProxy, asset, oldLiquidationFactor, newLiquidationFactor);\n    }\n\n    function updateAssetSupplyCap(address cometProxy, address asset, uint128 newSupplyCap) external governorOrMarketAdmin {\n        uint assetIndex = getAssetIndex(cometProxy, asset);\n        uint128 oldSupplyCap = configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap;\n        configuratorParams[cometProxy].assetConfigs[assetIndex].supplyCap = newSupplyCap;\n        emit UpdateAssetSupplyCap(cometProxy, asset, oldSupplyCap, newSupplyCap);\n    }\n\n    /** Other helpers **/\n\n    /**\n     * @dev Determine index of asset that matches given address\n     */\n    function getAssetIndex(address cometProxy, address asset) public view returns (uint) {\n        AssetConfig[] memory assetConfigs = configuratorParams[cometProxy].assetConfigs;\n        uint numAssets = assetConfigs.length;\n        for (uint i = 0; i < numAssets; ) {\n            if (assetConfigs[i].asset == asset) {\n                return i;\n            }\n            unchecked { i++; }\n        }\n        revert AssetDoesNotExist();\n    }\n\n    /**\n     * @return The currently configured params for a Comet proxy\n     **/\n    function getConfiguration(address cometProxy) external view returns (Configuration memory) {\n        return configuratorParams[cometProxy];\n    }\n\n    /**\n     * @notice Deploy a new Comet implementation using the factory and Configuration for that Comet proxy\n     * @dev Note: Callable by anyone\n     */\n    function deploy(address cometProxy) external virtual returns (address) {\n        address newComet = CometFactory(factory[cometProxy]).clone(configuratorParams[cometProxy]);\n        emit CometDeployed(cometProxy, newComet);\n        return newComet;\n    }\n\n    /**\n     * @notice Transfers the governor rights to a new address\n     */\n    function transferGovernor(address newGovernor) external {\n        if (msg.sender != governor) revert Unauthorized();\n        address oldGovernor = governor;\n        governor = newGovernor;\n        emit GovernorTransferred(oldGovernor, newGovernor);\n    }\n}\n"},{"file_path":"contracts/IComp.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./ERC20.sol\";\n\n/**\n * @dev Interface for interacting with COMP.\n * Note Not a comprehensive interface\n */\ninterface IComp is ERC20 {\n    function delegate(address delegatee) external;\n    function getCurrentVotes(address account) external view returns (uint96);\n}\n"},{"file_path":"contracts/vendor/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        assembly {\n            r.slot := slot\n        }\n    }\n}\n"},{"file_path":"contracts/vendor/proxy/ERC1967/ERC1967Upgrade.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n    // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function _getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Perform implementation upgrade\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeTo(address newImplementation) internal {\n        _setImplementation(newImplementation);\n        emit Upgraded(newImplementation);\n    }\n\n    /**\n     * @dev Perform implementation upgrade with additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCall(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _upgradeTo(newImplementation);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(newImplementation, data);\n        }\n    }\n\n    /**\n     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        // Upgrades from old implementations will perform a rollback test. This test requires the new\n        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n        // this special case will break upgrade paths from old UUPS implementation to new ones.\n        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n            _setImplementation(newImplementation);\n        } else {\n            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n                require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n            } catch {\n                revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n            }\n            _upgradeToAndCall(newImplementation, data, forceCall);\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Returns the current admin.\n     */\n    function _getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {AdminChanged} event.\n     */\n    function _changeAdmin(address newAdmin) internal {\n        emit AdminChanged(_getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n     */\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Emitted when the beacon is upgraded.\n     */\n    event BeaconUpgraded(address indexed beacon);\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function _getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n        require(\n            Address.isContract(IBeacon(newBeacon).implementation()),\n            \"ERC1967: beacon implementation is not a contract\"\n        );\n        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n    }\n\n    /**\n     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n     *\n     * Emits a {BeaconUpgraded} event.\n     */\n    function _upgradeBeaconToAndCall(\n        address newBeacon,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _setBeacon(newBeacon);\n        emit BeaconUpgraded(newBeacon);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        }\n    }\n}\n"},{"file_path":"contracts/bulkers/MainnetBulkerWithWstETHSupport.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./BaseBulker.sol\";\nimport \"../IWstETH.sol\";\n\n/**\n * @title Compound's Bulker contract for Ethereum mainnet\n * @notice Executes multiple Comet-related actions in a single transaction\n * @author Compound\n */\ncontract MainnetBulkerWithWstETHSupport is BaseBulker {\n    /** General configuration constants **/\n\n    /// @notice The address of Lido staked ETH\n    address public immutable steth;\n\n    /// @notice The address of Lido wrapped staked ETH\n    address public immutable wsteth;\n\n    /** Actions **/\n\n    /// @notice The action for supplying staked ETH to Comet\n    bytes32 public constant ACTION_SUPPLY_STETH = \"ACTION_SUPPLY_STETH\";\n\n    /// @notice The action for withdrawing staked ETH from Comet\n    bytes32 public constant ACTION_WITHDRAW_STETH = \"ACTION_WITHDRAW_STETH\";\n\n    /** Custom errors **/\n\n    error UnsupportedBaseAsset();\n\n    /**\n     * @notice Construct a new MainnetBulker instance\n     * @param admin_ The admin of the Bulker contract\n     * @param weth_ The address of wrapped ETH\n     * @param wsteth_ The address of Lido wrapped staked ETH\n     **/\n    constructor(\n        address admin_,\n        address payable weth_,\n        address wsteth_\n    ) BaseBulker(admin_, weth_) {\n        wsteth = wsteth_;\n        steth = IWstETH(wsteth_).stETH();\n    }\n\n    /**\n     * @notice Handles actions specific to the Ethereum mainnet version of Bulker, specifically supplying and withdrawing stETH\n     */\n    function handleAction(bytes32 action, bytes calldata data) override internal {\n        if (action == ACTION_SUPPLY_STETH) {\n            (address comet, address to, uint stETHAmount) = abi.decode(data, (address, address, uint));\n            supplyStEthTo(comet, to, stETHAmount);\n        } else if (action == ACTION_WITHDRAW_STETH) {\n            (address comet, address to, uint wstETHAmount) = abi.decode(data, (address, address, uint));\n            withdrawStEthTo(comet, to, wstETHAmount);\n        } else {\n            revert UnhandledAction();\n        }\n    }\n\n    /**\n     * @notice Wraps stETH to wstETH and supplies to a user in Comet\n     * @dev Note: This contract must have permission to manage msg.sender's Comet account\n     * @dev Note: Supports `stETHAmount` of `uint256.max` to fully repay the wstETH debt\n     * @dev Note: Only for the cwstETHv3 market\n     */\n    function supplyStEthTo(address comet, address to, uint stETHAmount) internal {\n        if(CometInterface(comet).baseToken() != wsteth) revert UnsupportedBaseAsset();\n        uint256 _stETHAmount = stETHAmount == type(uint256).max\n            ? IWstETH(wsteth).getStETHByWstETH(CometInterface(comet).borrowBalanceOf(msg.sender))\n            : stETHAmount;\n        doTransferIn(steth, msg.sender, _stETHAmount);\n        ERC20(steth).approve(wsteth, _stETHAmount);\n        uint wstETHAmount = IWstETH(wsteth).wrap(_stETHAmount);\n        ERC20(wsteth).approve(comet, wstETHAmount);\n        CometInterface(comet).supplyFrom(address(this), to, wsteth, wstETHAmount);\n    }\n\n    /**\n     * @notice Withdraws wstETH from Comet, unwraps it to stETH, and transfers it to a user\n     * @dev Note: This contract must have permission to manage msg.sender's Comet account\n     * @dev Note: Supports `amount` of `uint256.max` to withdraw all wstETH from Comet\n     * @dev Note: Only for the cwstETHv3 market\n     */\n    function withdrawStEthTo(address comet, address to, uint stETHAmount) internal {\n        if(CometInterface(comet).baseToken() != wsteth) revert UnsupportedBaseAsset();\n        uint wstETHAmount = stETHAmount == type(uint256).max\n            ? CometInterface(comet).balanceOf(msg.sender)\n            : IWstETH(wsteth).getWstETHByStETH(stETHAmount);\n        CometInterface(comet).withdrawFrom(msg.sender, address(this), wsteth, wstETHAmount);\n        uint unwrappedStETHAmount = IWstETH(wsteth).unwrap(wstETHAmount);\n        doTransferOut(steth, to, unwrappedStETHAmount);\n    }\n    \n    /**\n     * @notice Submits received ether to get stETH and wraps it to wstETH, received wstETH is transferred to Comet\n     */\n    function deposit(address comet) external payable {\n        if(msg.sender != admin) revert Unauthorized();\n        if(CometInterface(comet).baseToken() != wsteth) revert UnsupportedBaseAsset();\n        (bool success, ) = payable(wsteth).call{value: msg.value}(new bytes(0));\n        if(!success) revert TransferOutFailed();\n\n        uint wstETHAmount = ERC20(wsteth).balanceOf(address(this));\n        doTransferOut(wsteth, comet, wstETHAmount);\n    }\n}"},{"file_path":"contracts/bridges/test/BaseBridgeReceiverHarness.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../BaseBridgeReceiver.sol\";\n\ncontract BaseBridgeReceiverHarness is BaseBridgeReceiver {\n    function processMessageExternal(\n        address rootMessageSender,\n        bytes calldata data\n    ) external {\n        processMessage(rootMessageSender, data);\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-core/contracts/interfaces/pool/IUniswapV3PoolDerivedState.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title Pool state that is not stored\n/// @notice Contains view functions to provide information about the pool that is computed rather than stored on the\n/// blockchain. The functions here may have variable gas costs.\ninterface IUniswapV3PoolDerivedState {\n    /// @notice Returns the cumulative tick and liquidity as of each timestamp `secondsAgo` from the current block timestamp\n    /// @dev To get a time weighted average tick or liquidity-in-range, you must call this with two values, one representing\n    /// the beginning of the period and another for the end of the period. E.g., to get the last hour time-weighted average tick,\n    /// you must call it with secondsAgos = [3600, 0].\n    /// @dev The time weighted average tick represents the geometric time weighted average price of the pool, in\n    /// log base sqrt(1.0001) of token1 / token0. The TickMath library can be used to go from a tick value to a ratio.\n    /// @param secondsAgos From how long ago each cumulative tick and liquidity value should be returned\n    /// @return tickCumulatives Cumulative tick values as of each `secondsAgos` from the current block timestamp\n    /// @return secondsPerLiquidityCumulativeX128s Cumulative seconds per liquidity-in-range value as of each `secondsAgos` from the current block\n    /// timestamp\n    function observe(uint32[] calldata secondsAgos)\n        external\n        view\n        returns (int56[] memory tickCumulatives, uint160[] memory secondsPerLiquidityCumulativeX128s);\n\n    /// @notice Returns a snapshot of the tick cumulative, seconds per liquidity and seconds inside a tick range\n    /// @dev Snapshots must only be compared to other snapshots, taken over a period for which a position existed.\n    /// I.e., snapshots cannot be compared if a position is not held for the entire period between when the first\n    /// snapshot is taken and the second snapshot is taken.\n    /// @param tickLower The lower tick of the range\n    /// @param tickUpper The upper tick of the range\n    /// @return tickCumulativeInside The snapshot of the tick accumulator for the range\n    /// @return secondsPerLiquidityInsideX128 The snapshot of seconds per liquidity for the range\n    /// @return secondsInside The snapshot of seconds per liquidity for the range\n    function snapshotCumulativesInside(int24 tickLower, int24 tickUpper)\n        external\n        view\n        returns (\n            int56 tickCumulativeInside,\n            uint160 secondsPerLiquidityInsideX128,\n            uint32 secondsInside\n        );\n}\n"},{"file_path":"contracts/live-test/ConfiguratorLiveTest.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../Configurator.sol\";\n\n/**\n * @title ICometFactoryV2LiveTest\n * @notice Minimal interface for the external live-test Comet factory. \n */\ninterface ICometFactoryV2LiveTest {\n    function clone(CometConfiguration.Configuration calldata config, bytes32 testingPurpose) external returns (address);\n}\n\n/**\n * @title ConfiguratorLiveTest\n * @author Woof\n * @notice Test-only Configurator variant. Extends {Configurator} with a per-Comet {testingPurpose}\n *         that is forwarded to the live-test factory's `clone(Configuration,bytes32)` when deploying a\n *         {CometLiveTest}. Real funds must never be deposited into markets deployed through this\n *         Configurator (see the banner in {CometLiveTest}).\n */\ncontract ConfiguratorLiveTest is Configurator {\n    /// @notice Emitted when the testing purpose for a Comet proxy is updated.\n    /// @param cometProxy The Comet proxy whose testing purpose was updated.\n    /// @param oldTestingPurpose The previous testing purpose.\n    /// @param newTestingPurpose The new testing purpose.\n    event SetTestingPurpose(address indexed cometProxy, bytes32 oldTestingPurpose, bytes32 newTestingPurpose);\n\n    /// @notice Mapping of Comet proxy addresses to the testing purpose forwarded to the factory on deploy.\n    mapping(address => bytes32) public testingPurposePerComet;\n\n    function setTestingPurpose(address cometProxy, bytes32 testingPurpose) external {\n        if (msg.sender != governor) revert Unauthorized();\n\n        bytes32 oldTestingPurpose = testingPurposePerComet[cometProxy];\n        testingPurposePerComet[cometProxy] = testingPurpose;\n        emit SetTestingPurpose(cometProxy, oldTestingPurpose, testingPurpose);\n    }\n\n    /**\n     * @notice Deploy a new CometLiveTest implementation using the live-test factory, Configuration and\n     *         testing purpose for that Comet proxy.\n     * @dev Overrides {Configurator.deploy}. Callable by anyone. Routes through {ICometFactoryV2LiveTest}\n     *      so the Configuration is encoded against this branch's own struct definition.\n     * @param cometProxy The Comet proxy whose configuration and testing purpose are used.\n     * @return newComet The address of the newly deployed CometLiveTest implementation.\n     */\n    function deploy(address cometProxy) external override returns (address newComet) {\n        newComet = ICometFactoryV2LiveTest(factory[cometProxy]).clone(\n            configuratorParams[cometProxy],\n            testingPurposePerComet[cometProxy]\n        );\n        emit CometDeployed(cometProxy, newComet);\n    }\n}"},{"file_path":"contracts/liquidator/vendor/@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.6.0;\n\nimport '../../../../@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nlibrary TransferHelper {\n    /// @notice Transfers tokens from the targeted address to the given destination\n    /// @notice Errors with 'STF' if transfer fails\n    /// @param token The contract address of the token to be transferred\n    /// @param from The originating address from which the tokens will be transferred\n    /// @param to The destination address of the transfer\n    /// @param value The amount to be transferred\n    function safeTransferFrom(\n        address token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        (bool success, bytes memory data) =\n            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');\n    }\n\n    /// @notice Transfers tokens from msg.sender to a recipient\n    /// @dev Errors with ST if transfer fails\n    /// @param token The contract address of the token which will be transferred\n    /// @param to The recipient of the transfer\n    /// @param value The value of the transfer\n    function safeTransfer(\n        address token,\n        address to,\n        uint256 value\n    ) internal {\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');\n    }\n\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\n    /// @dev Errors with 'SA' if transfer fails\n    /// @param token The contract address of the token to be approved\n    /// @param to The target of the approval\n    /// @param value The amount of the given token the target will be allowed to spend\n    function safeApprove(\n        address token,\n        address to,\n        uint256 value\n    ) internal {\n        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));\n        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');\n    }\n\n    /// @notice Transfers ETH to the recipient address\n    /// @dev Fails with `STE`\n    /// @param to The destination of the transfer\n    /// @param value The value to be transferred\n    function safeTransferETH(address to, uint256 value) internal {\n        (bool success, ) = to.call{value: value}(new bytes(0));\n        require(success, 'STE');\n    }\n}\n"},{"file_path":"contracts/CometProxyAdmin.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./vendor/proxy/transparent/ProxyAdmin.sol\";\nimport \"./marketupdates/MarketAdminPermissionCheckerInterface.sol\";\n\ninterface Deployable {\n  function deploy(address cometProxy) external returns (address);\n}\n\ncontract CometProxyAdmin is ProxyAdmin {\n\n    /// @notice MarketAdminPermissionChecker contract which is used to check if the caller has permission to perform market updates(or deployment)\n    MarketAdminPermissionCheckerInterface public marketAdminPermissionChecker;\n\n    event SetMarketAdminPermissionChecker(address indexed oldMarketAdminPermissionChecker, address indexed newMarketAdminPermissionChecker);\n    error Unauthorized();\n\n    /**\n     * @dev Ensures that the caller is either the owner or the market admin.\n     * This delegates the permission check logic to the MarketAdminPermissionChecker contract.\n     */\n    modifier ownerOrMarketAdmin {\n        if(_msgSender() != owner()) marketAdminPermissionChecker.checkUpdatePermission(_msgSender());\n        _;\n    }\n\n    /**\n     * @dev Initializes the contract setting the specified address as the initial owner.\n     * @param initialOwner The address to set as the owner of the contract.\n     */\n    constructor(address initialOwner) ProxyAdmin(initialOwner) {}\n\n    /**\n     * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy\n     *  Requirements:\n     *   - This contract must be the admin of `CometProxy`\n     */\n    function deployAndUpgradeTo(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy) public virtual ownerOrMarketAdmin {\n        address newCometImpl = configuratorProxy.deploy(address(cometProxy));\n        _upgrade(cometProxy, newCometImpl);\n    }\n\n    /**\n     * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy, then call the function\n     *  Requirements:\n     *   - This contract must be the admin of `CometProxy`\n     */\n    function deployUpgradeToAndCall(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy, bytes memory data) public virtual ownerOrMarketAdmin {\n        address newCometImpl = configuratorProxy.deploy(address(cometProxy));\n        _upgradeAndCall(cometProxy, newCometImpl, data);\n    }\n\n    /**\n    * @notice Sets the MarketAdminPermissionChecker contract\n    * @dev Note: Only callable by main-governor-timelock\n    **/\n    function setMarketAdminPermissionChecker(MarketAdminPermissionCheckerInterface newMarketAdminPermissionChecker) external {\n        if (_msgSender() != owner()) revert Unauthorized();\n        address oldMarketAdminPermissionChecker = address(marketAdminPermissionChecker);\n        marketAdminPermissionChecker = newMarketAdminPermissionChecker;\n        emit SetMarketAdminPermissionChecker(oldMarketAdminPermissionChecker, address(newMarketAdminPermissionChecker));\n    }\n\n\n    /**\n     * @dev Custom upgrade function that allows owner and marketAdmin to call it\n     */\n    function _upgrade(TransparentUpgradeableProxy proxy, address implementation) private {\n        proxy.upgradeTo(implementation);\n    }\n\n    /**\n     * @dev Custom upgradeAndCall function that allows owner and marketAdmin to call it\n     */\n    function _upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) private {\n        proxy.upgradeToAndCall(implementation, data);\n    }\n}\n"},{"file_path":"contracts/vendor/proxy/transparent/TransparentUpgradeableProxy.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n    /**\n     * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n     * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n     */\n    constructor(\n        address _logic,\n        address admin_,\n        bytes memory _data\n    ) payable ERC1967Proxy(_logic, _data) {\n        assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n        _changeAdmin(admin_);\n    }\n\n    /**\n     * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n     */\n    modifier ifAdmin() {\n        if (msg.sender == _getAdmin()) {\n            _;\n        } else {\n            _fallback();\n        }\n    }\n\n    /**\n     * @dev Returns the current admin.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n     */\n    function admin() external ifAdmin returns (address admin_) {\n        admin_ = _getAdmin();\n    }\n\n    /**\n     * @dev Returns the current implementation.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n     *\n     * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n     * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n     * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n     */\n    function implementation() external ifAdmin returns (address implementation_) {\n        implementation_ = _implementation();\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {AdminChanged} event.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n     */\n    function changeAdmin(address newAdmin) external virtual ifAdmin {\n        _changeAdmin(newAdmin);\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n     */\n    function upgradeTo(address newImplementation) external ifAdmin {\n        _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n     * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n     * proxied contract.\n     *\n     * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n     */\n    function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n        _upgradeToAndCall(newImplementation, data, true);\n    }\n\n    /**\n     * @dev Returns the current admin.\n     */\n    function _admin() internal view virtual returns (address) {\n        return _getAdmin();\n    }\n\n    /**\n     * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n     */\n    function _beforeFallback() internal virtual override {\n        require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n        super._beforeFallback();\n    }\n}\n"},{"file_path":"contracts/bridges/linea/LineaBridgeReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./IMessageService.sol\";\nimport \"../SweepableBridgeReceiver.sol\";\n\ncontract LineaBridgeReceiver is SweepableBridgeReceiver {\n    /// @notice Address of Linea Message Service\n    IMessageService public messageService;\n\n    constructor(address _messageService) {\n        messageService = IMessageService(_messageService);\n    }\n\n    fallback() external payable {\n        if (msg.sender != address(messageService)) revert Unauthorized();\n        processMessage(messageService.sender(), msg.data);\n    }\n}\n"},{"file_path":"contracts/liquidator/interfaces/IStableSwap.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.15;\n\n/**\n * @dev Interface for interacting with Curve pools\n * Note Not a comprehensive interface\n */\n\ninterface IStableSwap {\n    function coins(uint256 i) external view returns (address);\n    function exchange(int128 i, int128 j, uint256 _dx, uint256 _min_dy) external payable returns (uint256);\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/liquidator/vendor/@uniswap/v3-periphery/contracts/libraries/CallbackValidation.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.15;\n\nimport '../../../v3-core/contracts/interfaces/IUniswapV3Pool.sol';\nimport './PoolAddress.sol';\n\n/// @notice Provides validation for callbacks from Uniswap V3 Pools\nlibrary CallbackValidation {\n    /// @notice Returns the address of a valid Uniswap V3 Pool\n    /// @param factory The contract address of the Uniswap V3 factory\n    /// @param tokenA The contract address of either token0 or token1\n    /// @param tokenB The contract address of the other token\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n    /// @return pool The V3 pool contract address\n    function verifyCallback(\n        address factory,\n        address tokenA,\n        address tokenB,\n        uint24 fee\n    ) internal view returns (IUniswapV3Pool pool) {\n        return verifyCallback(factory, PoolAddress.getPoolKey(tokenA, tokenB, fee));\n    }\n\n    /// @notice Returns the address of a valid Uniswap V3 Pool\n    /// @param factory The contract address of the Uniswap V3 factory\n    /// @param poolKey The identifying key of the V3 pool\n    /// @return pool The V3 pool contract address\n    function verifyCallback(address factory, PoolAddress.PoolKey memory poolKey)\n        internal\n        view\n        returns (IUniswapV3Pool pool)\n    {\n        pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));\n        require(msg.sender == address(pool));\n    }\n}\n"},{"file_path":"contracts/marketupdates/CometProxyAdminOld.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./../vendor/proxy/transparent/ProxyAdmin.sol\";\n\ninterface Deployable {\n    function deploy(address cometProxy) external returns (address);\n}\n\n/**\n * @dev This contract is just to simulate the full deployment process of market updates. Should be deleted after the market updates are deployed.\n */\ncontract CometProxyAdminOld is ProxyAdmin {\n\n    /**\n     * @dev Initializes the contract setting the specified address as the initial owner.\n     * @param initialOwner The address to set as the owner of the contract.\n     */\n    constructor(address initialOwner) ProxyAdmin(initialOwner) {}\n\n    /**\n     * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy\n     *  Requirements:\n     *   - This contract must be the admin of `CometProxy`\n     */\n    function deployAndUpgradeTo(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy) public virtual onlyOwner {\n        address newCometImpl = configuratorProxy.deploy(address(cometProxy));\n        upgrade(cometProxy, newCometImpl);\n    }\n\n    /**\n     * @dev Deploy a new Comet and upgrade the implementation of the Comet proxy, then call the function\n     *  Requirements:\n     *   - This contract must be the admin of `CometProxy`\n     */\n    function deployUpgradeToAndCall(Deployable configuratorProxy, TransparentUpgradeableProxy cometProxy, bytes memory data) public virtual onlyOwner {\n        address newCometImpl = configuratorProxy.deploy(address(cometProxy));\n        upgradeAndCall(cometProxy, newCometImpl, data);\n    }\n}\n"},{"file_path":"contracts/IAny2EVMMessageReceiver.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nstruct Any2EVMMessage {\n    bytes32 messageId;\n    uint64 sourceChainSelector;\n    bytes sender;\n    bytes data;\n    EVMTokenAmount[] destTokenAmounts;\n}\n\nstruct EVMTokenAmount {\n    address token;\n    uint256 amount;\n}\n\n/// @notice Application contracts that intend to receive messages from\n/// the router should implement this interface.\ninterface IAny2EVMMessageReceiver {\n    /// @notice Called by the Router to deliver a message.\n    /// If this reverts, any token transfers also revert. The message\n    /// will move to a FAILED state and become available for manual execution.\n    /// @param message CCIP Message\n    /// @dev Note ensure you check the msg.sender is the OffRampRouter\n    function ccipReceive(Any2EVMMessage calldata message) external;\n}\n"},{"file_path":"contracts/test/CometHarness.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"../Comet.sol\";\n\ncontract CometHarness is Comet {\n    uint public nowOverride;\n\n    constructor(Configuration memory config) Comet(config) {}\n\n    function getNowInternal() override internal view returns (uint40) {\n        return nowOverride > 0 ? uint40(nowOverride) : super.getNowInternal();\n    }\n\n    function getNow() public view returns (uint40) {\n        return getNowInternal();\n    }\n\n    function setNow(uint now_) external {\n        nowOverride = now_;\n    }\n\n    function setTotalsBasic(TotalsBasic memory totals) external {\n        baseSupplyIndex = totals.baseSupplyIndex;\n        baseBorrowIndex = totals.baseBorrowIndex;\n        trackingSupplyIndex = totals.trackingSupplyIndex;\n        trackingBorrowIndex = totals.trackingBorrowIndex;\n        totalSupplyBase = totals.totalSupplyBase;\n        totalBorrowBase = totals.totalBorrowBase;\n        lastAccrualTime = totals.lastAccrualTime;\n    }\n\n    function setTotalsCollateral(address asset, TotalsCollateral memory totals) external {\n        totalsCollateral[asset] = totals;\n    }\n\n    function setBasePrincipal(address account, int104 principal) external {\n        userBasic[account].principal = principal;\n    }\n\n    function setCollateralBalance(address account, address asset, uint128 balance) external {\n        uint128 oldBalance = userCollateral[account][asset].balance;\n        userCollateral[account][asset].balance = balance;\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\n        updateAssetsIn(account, assetInfo, oldBalance, balance);\n    }\n\n    function updateAssetsInExternal(\n        address account,\n        address asset,\n        uint128 initialUserBalance,\n        uint128 finalUserBalance\n    ) external {\n        AssetInfo memory assetInfo = getAssetInfoByAddress(asset);\n        updateAssetsIn(account, assetInfo, initialUserBalance, finalUserBalance);\n    }\n\n    function getAssetList(address account) external view returns (address[] memory result) {\n        uint16 assetsIn = userBasic[account].assetsIn;\n\n        uint8 count = 0;\n        for (uint8 i = 0; i < numAssets; i++) {\n            if (isInAsset(assetsIn, i)) {\n                count++;\n            }\n        }\n\n        result = new address[](count);\n\n        uint j = 0;\n        for (uint8 i = 0; i < numAssets; i++) {\n            if (isInAsset(assetsIn, i)) {\n                result[j] = getAssetInfo(i).asset;\n                j++;\n            }\n        }\n\n        return result;\n    }\n\n    function accrue() external {\n        accrueInternal();\n    }\n}"},{"file_path":"contracts/IGovernorBravo.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\n/**\n * @dev Interface for interacting with Governor bravo.\n * Note Not a comprehensive interface\n */\ninterface IGovernorBravo {\n    enum ProposalState {\n        Pending,\n        Active,\n        Canceled,\n        Defeated,\n        Succeeded,\n        Queued,\n        Expired,\n        Executed\n    }\n\n    struct Proposal {\n        uint id;\n        address proposer;\n        uint eta;\n        uint startBlock;\n        uint endBlock;\n        uint forVotes;\n        uint againstVotes;\n        uint abstainVotes;\n        bool canceled;\n        bool executed;\n    }\n\n    event ProposalCreated(\n        uint256 proposalId,\n        address proposer,\n        address[] targets,\n        uint256[] values,\n        string[] signatures,\n        bytes[] calldatas,\n        uint256 startBlock,\n        uint256 endBlock,\n        string description\n    );\n    event ProposalCanceled(uint256 proposalId);\n    event ProposalQueued(uint256 proposalId, uint256 eta);\n    event ProposalExecuted(uint256 proposalId);\n\n    function MIN_VOTING_PERIOD() external view returns (uint256);\n    function MIN_VOTING_DELAY() external view returns (uint256);\n    function MIN_PROPOSAL_THRESHOLD() external view returns (uint256);\n\n    function comp() external view returns (address); // for testnet only\n    function token() external view returns (address);\n    function proposalEta(uint256) external view returns (uint256);\n    function timelock() external view returns (address);\n    function proposalCount() external view returns (uint256);\n    function proposals(uint256 proposalId) external view returns (Proposal memory);\n    function votingDelay() external view returns (uint256);\n    function votingPeriod() external view returns (uint256);\n    function state(uint256 proposalId) external view returns (ProposalState);\n    function propose(\n        address[] memory targets,\n        uint256[] memory values,\n        bytes[] memory calldatas,\n        string memory description\n    ) external returns (uint256 proposalId);\n    function queue(uint256 proposalId) external;\n    function execute(uint256 proposalId) external;\n    function castVote(uint256 proposalId, uint8 support) external returns (uint256 balance);\n    function proposalDetails(uint proposalId) external view returns (address[] memory targets, uint[] memory values, bytes[] memory calldatas, bytes32 descriptionHash);\n    function proposalSnapshot(uint256 proposalId) external view returns (uint256);\n    function quorum(uint256 timepoint) external view returns (uint256);\n    function proposalVotes(uint256 proposalId) external view returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes);\n    function proposalDeadline(uint256 proposalId) external view returns (uint256);\n    function castVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) external returns (uint256);\n}\n"},{"file_path":"contracts/vendor/access/Ownable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.15;\n\nimport {Context} from \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},{"file_path":"contracts/marketupdates/MarketUpdateTimelock.sol","source_code":"// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.15;\n\n/**\n* @title MarketUpdateTimelock\n* @notice This contract allows for the execution of transactions after a delay and a proposal mechanism.\n* @dev This contract is used for the market updates. The market updates are proposed by the marketAdmin.\n* Few important points to note:\n* 1) The call to queue, cancel, and execute transaction functions should come from the marketUpdateProposer.\n* 2) The marketUpdateProposer can only be set by the governor.\n*\n*/\n\ncontract MarketUpdateTimelock {\n    uint public constant GRACE_PERIOD = 14 days;\n    uint public constant MINIMUM_DELAY = 2 days;\n    uint public constant MAXIMUM_DELAY = 30 days;\n\n    address public governor;\n    address public marketUpdateProposer;\n    uint public delay;\n\n    mapping(bytes32 => bool) public queuedTransactions;\n\n    event SetGovernor(address indexed oldGovernor, address indexed newGovernor);\n    event SetMarketUpdateProposer(address indexed oldMarketAdmin, address indexed newMarketAdmin);\n    event SetDelay(uint indexed newDelay);\n    event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\n    event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature,  bytes data, uint eta);\n    event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta);\n    \n    constructor(address governor_, uint delay_) public {\n        require(delay_ >= MINIMUM_DELAY, \"MarketUpdateTimelock::constructor: Delay must exceed minimum delay.\");\n        require(delay_ <= MAXIMUM_DELAY, \"MarketUpdateTimelock::setDelay: Delay must not exceed maximum delay.\");\n\n        governor = governor_;\n        delay = delay_;\n    }\n\n    fallback() external payable { }\n\n    /**\n     * @notice Sets a new delay for executing transactions\n     * @param delay_ The new delay in seconds\n     */\n    function setDelay(uint delay_) public {\n        require(msg.sender == governor, \"MarketUpdateTimelock::setDelay: Call must come from the Main Governor Timelock.\");\n        require(delay_ >= MINIMUM_DELAY, \"MarketUpdateTimelock::setDelay: Delay must exceed minimum delay.\");\n        require(delay_ <= MAXIMUM_DELAY, \"MarketUpdateTimelock::setDelay: Delay must not exceed maximum delay.\");\n        delay = delay_;\n\n        emit SetDelay(delay);\n    }\n\n    /**\n     * @notice Transfers governor role to a new address\n     * @param newGovernor The address of the new governor\n     */\n    function setGovernor(address newGovernor) public {\n        require(msg.sender == governor, \"MarketUpdateTimelock::setGovernor: Call must come from governor.\");\n        address oldGovernor = governor;\n        governor = newGovernor;\n        emit SetGovernor(oldGovernor, newGovernor);\n    }\n\n    /**\n     * @notice Sets a new market update proposer\n     * @param newMarketUpdateProposer The address of the new proposer\n     */\n    function setMarketUpdateProposer(address newMarketUpdateProposer) external {\n        require(msg.sender == governor, \"MarketUpdateTimelock::setMarketUpdateProposer: Call must come from governor.\");\n        address oldMarketUpdateProposer = marketUpdateProposer;\n        marketUpdateProposer = newMarketUpdateProposer;\n        emit SetMarketUpdateProposer(oldMarketUpdateProposer, newMarketUpdateProposer);\n    }\n\n    /**\n     * @notice Queues a transaction for execution\n     * @param target The address of the target contract\n     * @param value The ETH value to send with the transaction\n     * @param signature The function signature to call\n     * @param data The calldata for the function call\n     * @param eta The time when the transaction can be executed\n     * @return The hash of the queued transaction\n     */\n    function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) {\n        require(msg.sender == marketUpdateProposer, \"MarketUpdateTimelock::queueTransaction: Call must come from marketUpdateProposer.\");\n        require(eta >= getBlockTimestamp() + delay, \"MarketUpdateTimelock::queueTransaction: Estimated execution block must satisfy delay.\");\n\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        queuedTransactions[txHash] = true;\n\n        emit QueueTransaction(txHash, target, value, signature, data, eta);\n        return txHash;\n    }\n\n    /**\n     * @notice Cancels a previously queued transaction\n     * @param target The address of the target contract\n     * @param value The ETH value sent with the transaction\n     * @param signature The function signature\n     * @param data The calldata for the function\n     * @param eta The time when the transaction was scheduled to execute\n     */\n    function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public {\n        require(msg.sender == marketUpdateProposer, \"MarketUpdateTimelock::cancelTransaction: Call must come from marketUpdateProposer.\");\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        queuedTransactions[txHash] = false;\n\n        emit CancelTransaction(txHash, target, value, signature, data, eta);\n    }\n\n    /**\n     * @notice Executes a queued transaction\n     * @param target The address of the target contract\n     * @param value The ETH value to send with the transaction\n     * @param signature The function signature to call\n     * @param data The calldata for the function call\n     * @param eta The time when the transaction was scheduled to execute\n     * @return The return data from the executed transaction\n     */\n    function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) {\n        require(msg.sender == marketUpdateProposer, \"MarketUpdateTimelock::executeTransaction: Call must come from marketUpdateProposer.\");\n        bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta));\n        require(queuedTransactions[txHash], \"MarketUpdateTimelock::executeTransaction: Transaction hasn't been queued.\");\n        require(getBlockTimestamp() >= eta, \"MarketUpdateTimelock::executeTransaction: Transaction hasn't surpassed time lock.\");\n        require(getBlockTimestamp() <= eta + GRACE_PERIOD, \"MarketUpdateTimelock::executeTransaction: Transaction is stale.\");\n\n        queuedTransactions[txHash] = false;\n\n        bytes memory callData;\n\n        if (bytes(signature).length == 0) {\n            callData = data;\n        } else {\n            callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data);\n        }\n\n        // solium-disable-next-line security/no-call-value\n        (bool success, bytes memory returnData) = target.call{value: value}(callData);\n        require(success, \"MarketUpdateTimelock::executeTransaction: Transaction execution reverted.\");\n\n        emit ExecuteTransaction(txHash, target, value, signature, data, eta);\n\n        return returnData;\n    }\n\n    function getBlockTimestamp() internal view returns (uint) {\n        // solium-disable-next-line security/no-block-members\n        return block.timestamp;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\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":true,"is_partially_verified":false,"package_name":null,"constructor_args":"00000000000000000000000000000000000000000000000000000000000000200000000000000000000000003fb4d38ea7ec20d91917c09591490eeda38cf88a00000000000000000000000078e6317dd6d43ddbda00dce32c2cbafc99361a9d000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000880d36763bb470cd395b7d6c76b50446fa70ace50000000000000000000000000d4bd55a755134950027ce1f43190a354e648e200000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000007fe5cf2bea00000000000000000000000000000000000000000000000000002c5a79111e26000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000000062aff19e92200000000000000000000000000000000000000000000000000031f5c4ed2768000000000000000000000000000000000000000000000000000000354a6ba7a180000000000000000000000000000000000000000000000000000853a0d2313c000000000000000000000000000000000000000000000000000000038d7ea4c680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002540be40000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000048c2739500000000000000000000000000000000000000000000000000000000000000002a00000000000000000000000000000000000000000000000000000000000000009000000000000000000000000912ce59144191c1204e64559fe8253a0e49e65480000000000000000000000005998a5c516bd5e479e0b6aa6f243d372730b68d2000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000009b6e64a8ec600000000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000019c4215262765a0080000000000000000000000000000fc5a1a6eb076a2c7ad06ed22c90d7e710e35ad0a000000000000000000000000db98056fecfff59d032ab628337a4887110df3db00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000853a0d2313c00000000000000000000000000000000000000000000000000000a688906bd8b00000000000000000000000000000000000000000000000000000bcbce7f1b15000000000000000000000000000000000000000000000000008cbabcb5cd7210000000000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1000000000000000000000000b2988bdadc45c43e3fe1a728f715e94bee4db40600000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b84c09a3b9300000000000000000000000000000000000000000000000000000c3663566a5800000000000000000000000000000000000000000000000000000ce80612991d0000000000000000000000000000000000000000000000000878678326eac90000000000000000000000000000002f2a2543b76a4166549f7aab2e75bef0aefc5b0f000000000000000000000000cc392d2c3b37520e01712320be331d41f766101300000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000a688906bd8b00000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000000000174876e8000000000000000000000000005979d7b546e38e414f7e9822514be443a480052900000000000000000000000092014e7f331dfab2848a5872aa8b2e7b6f3ce8b400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000001b1ae4d6e2ef50000000000000000000000000000002416092f143378750bb29b79ed961ab195cceea50000000000000000000000005eba6ec97843163c92ab48a7ac0ccc8423c652b100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000058788cb94b1d8000000000000000000000000000057f5e098cad7a3d1eed53991d4d66c45c9af78120000000000000000000000005d173813b4505701e79e654b36a95e6c1fad44480000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005af3107a40000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d09acb80c1e8f2291862c4978a008791c91670030000000000000000000000005372bcf3486d59c23f5fc85745b41f180efff88100000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006c84a8f1c29108f47a79964b5fe888d4f4d0de40000000000000000000000000e808488e8627f6531ba79a13a9e0271b39abeb1c00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000b1a2bc2ec5000000000000000000000000000000000000000000000000000000bcbce7f1b1500000000000000000000000000000000000000000000000000000c7d713b49da00000000000000000000000000000000000000000000000000000000000000000000"}