creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/Comet.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometMainInterface.sol\";\nimport \"./ERC20.sol\";\nimport \"./vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.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    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 (AggregatorV3Interface(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 (AggregatorV3Interface(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, , , ) = AggregatorV3Interface(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        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 {\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"
      },
      "contracts/CometMainInterface.sol": {
        "content": "// 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 NoSelfTransfer();\n    error NotCollateralized();\n    error NotForSale();\n    error NotLiquidatable();\n    error Paused();\n    error SupplyCapExceeded();\n    error TimestampTooLarge();\n    error TooManyAssets();\n    error TooMuchSlippage();\n    error TransferInFailed();\n    error TransferOutFailed();\n    error Unauthorized();\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}"
      },
      "contracts/ERC20.sol": {
        "content": "// 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"
      },
      "contracts/vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": {
        "content": "// 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"
      },
      "contracts/CometCore.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.15;\n\nimport \"./CometConfiguration.sol\";\nimport \"./CometStorage.sol\";\nimport \"./CometMath.sol\";\nimport \"./vendor/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.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 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    /**\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"
      },
      "contracts/CometConfiguration.sol": {
        "content": "// 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"
      },
      "contracts/CometStorage.sol": {
        "content": "// 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"
      },
      "contracts/CometMath.sol": {
        "content": "// 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"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 1,
        "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"
          }
        }
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "viaIR": true,
      "libraries": {}
    }
  }}