creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/CErc20_PandoraDelegate.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\nimport \"contracts/CErc20_Pandora.sol\";\n\n/**\n * @title Compound's CErc20Delegate Contract\n * @notice CTokens which wrap an EIP-20 underlying and are delegated to\n * @author Compound\n */\ncontract CErc20_PandoraDelegate is CErc20_Pandora, CDelegateInterface {\n    /**\n     * @notice Construct an empty delegate\n     */\n    constructor() {}\n\n    /**\n     * @notice Called by the delegator on a delegate to initialize it for duty\n     * @param data The encoded bytes data for any initialization\n     */\n    function _becomeImplementation(bytes memory data) virtual override public {\n        // Shh -- currently unused\n        data;\n\n        // Shh -- we don't ever want this hook to be marked pure\n        if (false) {\n            implementation = address(0);\n        }\n\n        if (msg.sender != admin) {\n            revert Unauthorized();\n        }\n    }\n\n    /**\n     * @notice Called by the delegator on a delegate to forfeit its responsibility\n     */\n    function _resignImplementation() virtual override public {\n        // Shh -- we don't ever want this hook to be marked pure\n        if (false) {\n            implementation = address(0);\n        }\n\n        if (msg.sender != admin) {\n            revert Unauthorized();\n        }\n    }\n}\n"
      },
      "contracts/CErc20_Pandora.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\nimport \"contracts/CErc20.sol\";\n\ninterface ERC404Like {\n    function minted() external view returns (uint256);\n}\n\ncontract CErc20_Pandora is CErc20 {\n\n    function initialize(address underlying_,\n                        ComptrollerInterface comptroller_,\n                        InterestRateModel interestRateModel_,\n                        uint initialExchangeRateMantissa_,\n                        string memory name_,\n                        string memory symbol_,\n                        uint8 decimals_) public {\n        super.initialize(underlying_, comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_, CTokenStorage.MarketType.ERC20_INTEREST_MARKET);\n    }\n\n    /**\n     * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\n     *      This will revert due to insufficient balance or insufficient allowance.\n     *      This function returns the actual amount received,\n     *      which may be less than `amount` if there is a fee attached to the transfer.\n     *\n     *      Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\n     *            See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n     */\n    function doTransferIn(address from, uint amount) virtual override internal returns (uint) {\n        // Read from storage once\n        address underlying_ = underlying;\n        EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying_);\n        uint balanceBefore = EIP20Interface(underlying_).balanceOf(address(this));\n        \n        if (amount <= ERC404Like(underlying).minted()) {\n            revert TransferInvalidAmount();\n        }\n        token.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) {\n            revert TransferInFailed();\n        }\n\n        // Calculate the amount that was *actually* transferred\n        uint balanceAfter = EIP20Interface(underlying_).balanceOf(address(this));\n        return balanceAfter - balanceBefore;   // underflow already checked above, just subtract\n    }\n}\n"
      },
      "contracts/CErc20.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\nimport \"contracts/CToken.sol\";\n\n/**\n * @title Compound's CErc20 Contract\n * @notice CTokens which wrap an EIP-20 underlying\n * @author Compound\n */\ncontract CErc20 is CToken, CErc20Interface {\n    /**\n     * @notice Initialize the new money market\n     * @param underlying_ The address of the underlying asset\n     * @param comptroller_ The address of the Comptroller\n     * @param interestRateModel_ The address of the interest rate model\n     * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n     * @param name_ ERC-20 name of this token\n     * @param symbol_ ERC-20 symbol of this token\n     * @param decimals_ ERC-20 decimal precision of this token\n     * @param marketType_ MarketType enum of the token\n     */\n    function initialize(address underlying_,\n                        ComptrollerInterface comptroller_,\n                        InterestRateModel interestRateModel_,\n                        uint initialExchangeRateMantissa_,\n                        string memory name_,\n                        string memory symbol_,\n                        uint8 decimals_,\n                        MarketType marketType_) virtual public {\n        \n        if (marketType_ != CTokenStorage.MarketType.ERC20_MARKET && marketType_ != CTokenStorage.MarketType.ERC20_INTEREST_MARKET) {\n            revert InitializeInvalidMarketType();\n        }\n        marketType = marketType_;\n        \n        // CToken initialize does the bulk of the work\n        super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n        // Set underlying and sanity check it\n        underlying = underlying_;\n        EIP20Interface(underlying).totalSupply();\n    }\n\n    /*** User Interface ***/\n\n    /**\n     * @notice Sender supplies assets into the market and receives cTokens in exchange\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\n     * @param mintAmount The amount of the underlying asset to supply\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function mint(uint mintAmount) override external returns (uint) {\n\n        comptroller.autoEnterMarkets(msg.sender); // silent failure allowed\n\n        mintInternal(mintAmount);\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice Sender redeems cTokens in exchange for the underlying asset\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\n     * @param redeemTokens The number of cTokens to redeem into underlying\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function redeem(uint redeemTokens) override external returns (uint) {\n        redeemInternal(redeemTokens);\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\n     * @param redeemAmount The amount of underlying to redeem\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function redeemUnderlying(uint redeemAmount) override external returns (uint) {\n        redeemUnderlyingInternal(redeemAmount);\n        return NO_ERROR;\n    }\n\n    /**\n      * @notice Sender borrows assets from the protocol to their own address\n      * @param borrowAmount The amount of the underlying asset to borrow\n      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n      */\n    function borrow(uint borrowAmount) override external returns (uint) {\n\n        comptroller.autoEnterMarkets(msg.sender); // silent failure allowed\n\n        borrowInternal(borrowAmount);\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice Sender repays their own borrow\n     * @param repayAmount The amount to repay, or -1 for the full outstanding amount\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function repayBorrow(uint repayAmount) override external returns (uint) {\n        repayBorrowInternal(repayAmount);\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice Sender repays a borrow belonging to borrower\n     * @param borrower the account with the debt being payed off\n     * @param repayAmount The amount to repay, or -1 for the full outstanding amount\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function repayBorrowBehalf(address borrower, uint repayAmount) override external returns (uint) {\n        repayBorrowBehalfInternal(borrower, repayAmount);\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice The liquidator liquidates the borrowers collateral.\n     *  This function can only be called by the Comptroller.\n     * @param liquidator The liquidator who called Comptroller::batchLiquidateBorrow\n     * @param borrower The borrower of this cToken to be liquidated\n     * @param repayAmount The amount of the underlying borrowed asset to repay\n     * @return uint The amount of the underlying borrowed asset that was actually repaid\n     */\n    function _liquidateBorrow(address liquidator, address borrower, uint repayAmount) override external returns (uint) {\n        return _liquidateBorrowInternal(liquidator, borrower, repayAmount);\n    }\n\n    /**\n     * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to admin (timelock)\n     * @param token The address of the ERC-20 token to sweep\n     */\n    function sweepToken(EIP20NonStandardInterface token) virtual override external {\n        if (msg.sender != admin) {\n            revert Unauthorized();\n        }\n        if (address(token) == underlying) {\n            revert CannotSweepUnderlying();\n        }\n        uint256 balance = token.balanceOf(address(this));\n        token.transfer(admin, balance);\n    }\n\n    /**\n     * @notice The sender adds to reserves.\n     * @param addAmount The amount fo underlying token to add as reserves\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _addReserves(uint addAmount) override external returns (uint) {\n        return _addReservesInternal(addAmount);\n    }\n\n    /*** Safe Token ***/\n\n    /**\n     * @notice Gets balance of this contract in terms of the underlying\n     * @dev This excludes the value of the current message, if any\n     * @return The quantity of underlying tokens owned by this contract\n     */\n    function getCashPrior() virtual override internal view returns (uint) {\n        EIP20Interface token = EIP20Interface(underlying);\n        return token.balanceOf(address(this));\n    }\n\n    /**\n     * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\n     *      This will revert due to insufficient balance or insufficient allowance.\n     *      This function returns the actual amount received,\n     *      which may be less than `amount` if there is a fee attached to the transfer.\n     *\n     *      Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\n     *            See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n     */\n    function doTransferIn(address from, uint amount) virtual override internal returns (uint) {\n        // Read from storage once\n        address underlying_ = underlying;\n        EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying_);\n        uint balanceBefore = EIP20Interface(underlying_).balanceOf(address(this));\n        token.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) {\n            revert TransferInFailed();\n        }\n\n        // Calculate the amount that was *actually* transferred\n        uint balanceAfter = EIP20Interface(underlying_).balanceOf(address(this));\n        return balanceAfter - balanceBefore;   // underflow already checked above, just subtract\n    }\n\n    /**\n     * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\n     *      error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to\n     *      insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified\n     *      it is >= amount, this should not revert in normal conditions.\n     *\n     *      Note: This wrapper safely handles non-standard ERC-20 tokens that do not return a value.\n     *            See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n     */\n    function doTransferOut(address payable to, uint amount) virtual override internal {\n        EIP20NonStandardInterface token = EIP20NonStandardInterface(underlying);\n        token.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) {\n            revert TransferOutFailed();\n        }\n    }\n\n    // called only once by the comptroller during _supportMarket\n    function _ensureNonEmpty(address minter, uint amount) virtual override external {\n        _ensureNonEmptyInternal(minter, amount);\n    }\n}\n"
      },
      "contracts/CToken.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\nimport \"contracts/ComptrollerInterface.sol\";\nimport \"contracts/CTokenInterfaces.sol\";\nimport \"contracts/ErrorReporter.sol\";\nimport \"contracts/EIP20Interface.sol\";\nimport \"contracts/InterestRateModel.sol\";\nimport \"contracts/ExponentialNoError.sol\";\n\n\n/**\n * @title Compound's CToken Contract\n * @notice Abstract base for CTokens\n * @author Compound\n */\nabstract contract CToken is CTokenInterface, ExponentialNoError, TokenErrorReporter {\n    /**\n     * @notice Initialize the money market\n     * @param comptroller_ The address of the Comptroller\n     * @param interestRateModel_ The address of the interest rate model\n     * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n     * @param name_ EIP-20 name of this token\n     * @param symbol_ EIP-20 symbol of this token\n     * @param decimals_ EIP-20 decimal precision of this token\n     */\n    function initialize(ComptrollerInterface comptroller_,\n                        InterestRateModel interestRateModel_,\n                        uint initialExchangeRateMantissa_,\n                        string memory name_,\n                        string memory symbol_,\n                        uint8 decimals_) virtual public {\n        if (msg.sender != admin) {\n            revert Unauthorized();\n        }\n        if (accrualBlockNumber != 0 || borrowIndex != 0) {\n            revert AlreadyInitialized();\n        }\n\n        // Set initial exchange rate\n        initialExchangeRateMantissa = initialExchangeRateMantissa_;\n        if (initialExchangeRateMantissa == 0) {\n            revert InitializeExchangeRateInvalid();\n        }\n\n        // Set the comptroller\n        uint err = _setComptroller(comptroller_);\n        if (err != NO_ERROR) {\n            revert InitializeSetComptrollerFailed(err);\n        }\n\n        // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n        accrualBlockNumber = getBlockNumber();\n        borrowIndex = mantissaOne;\n\n        // Set the interest rate model (depends on block number / borrow index)\n        err = _setInterestRateModelFresh(interestRateModel_);\n        if (err != NO_ERROR) {\n            revert InitializeSetInterestRateModelFailed(err);\n        }\n\n        name = name_;\n        symbol = symbol_;\n        decimals = decimals_;\n\n        // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n        _notEntered = true;\n\n        if (marketType == CTokenStorage.MarketType.UNDEFINED_MARKET) {\n            revert InitializeMarketTypeNotSet();\n        }\n    }\n\n    /**\n     * @notice Transfer `tokens` tokens from `src` to `dst` by `spender`\n     * @dev Called by both `transfer` and `transferFrom` internally\n     * @param spender The address of the account performing the transfer\n     * @param src The address of the source account\n     * @param dst The address of the destination account\n     * @param tokens The number of tokens to transfer\n     * @return 0 if the transfer succeeded, else revert\n     */\n    function transferTokens(address spender, address src, address dst, uint tokens) virtual internal returns (uint) {\n        /* Fail if transfer not allowed */\n        uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\n        if (allowed != 0) {\n            revert TransferComptrollerRejection(allowed);\n        }\n\n        /* Do not allow self-transfers */\n        if (src == dst) {\n            revert TransferNotAllowed();\n        }\n\n        /* Get the allowance, infinite for the account owner */\n        uint startingAllowance = 0;\n        if (spender == src) {\n            startingAllowance = type(uint).max;\n        } else {\n            startingAllowance = transferAllowances[src][spender];\n        }\n\n        /* Do the calculations, checking for {under,over}flow */\n        uint allowanceNew = startingAllowance - tokens;\n        uint srcTokensNew = accountTokens[src] - tokens;\n        uint dstTokensNew = accountTokens[dst] + tokens;\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n        accountTokens[src] = srcTokensNew;\n        accountTokens[dst] = dstTokensNew;\n\n        /* Eat some of the allowance (if necessary) */\n        if (startingAllowance != type(uint).max) {\n            transferAllowances[src][spender] = allowanceNew;\n        }\n\n        /* We emit a Transfer event */\n        emit Transfer(src, dst, tokens);\n\n        return NO_ERROR;\n    }\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) override external nonReentrant returns (bool) {\n        return transferTokens(msg.sender, msg.sender, dst, amount) == NO_ERROR;\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 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) override external nonReentrant returns (bool) {\n        return transferTokens(msg.sender, src, dst, amount) == NO_ERROR;\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 amount The number of tokens that are approved (uint256.max means infinite)\n     * @return Whether or not the approval succeeded\n     */\n    function approve(address spender, uint256 amount) override external returns (bool) {\n        address src = msg.sender;\n        transferAllowances[src][spender] = amount;\n        emit Approval(src, spender, amount);\n        return true;\n    }\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) override external view returns (uint256) {\n        return transferAllowances[owner][spender];\n    }\n\n    /**\n     * @notice Get the token balance of the `owner`\n     * @param owner The address of the account to query\n     * @return The number of tokens owned by `owner`\n     */\n    function balanceOf(address owner) override external view returns (uint256) {\n        return accountTokens[owner];\n    }\n\n    /**\n     * @notice Get the underlying balance of the `owner`\n     * @dev This also accrues interest in a transaction\n     * @param owner The address of the account to query\n     * @return The amount of underlying owned by `owner`\n     */\n    function balanceOfUnderlying(address owner) override external returns (uint) {\n        Exp memory exchangeRate = Exp({mantissa: exchangeRateCurrent()});\n        return mul_ScalarTruncate(exchangeRate, accountTokens[owner]);\n    }\n\n    /**\n     * @notice Get a snapshot of the account's balances, and the cached exchange rate\n     * @dev This is used by comptroller to more efficiently perform liquidity checks.\n     * @param account Address of the account to snapshot\n     * @return (possible error, token balance, borrow balance, exchange rate mantissa, borrow interest balance (always 0))\n     */\n    function getAccountSnapshot(address account) virtual override external view returns (uint, uint, uint, uint, uint) {\n        return (\n            NO_ERROR,\n            accountTokens[account],\n            borrowBalanceStoredInternal(account),\n            exchangeRateStoredInternal(),\n            0\n        );\n    }\n\n    /**\n     * @dev Function to simply retrieve block number\n     *  This exists mainly for inheriting test contracts to stub this result.\n     */\n    function getBlockNumber() virtual internal view returns (uint) {\n        return block.number;\n    }\n\n    /**\n     * @notice Returns the current per-block borrow interest rate for this cToken\n     * @return The borrow interest rate per block, scaled by 1e18\n     */\n    function borrowRatePerBlock() override external view returns (uint) {\n        return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\n    }\n\n    /**\n     * @notice Returns the current per-block supply interest rate for this cToken\n     * @return The supply interest rate per block, scaled by 1e18\n     */\n    function supplyRatePerBlock() override external view returns (uint) {\n        return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\n    }\n\n    /**\n     * @notice Returns the current total borrows plus accrued interest\n     * @return The total borrows with interest\n     */\n    function totalBorrowsCurrent() override external nonReentrant returns (uint) {\n        accrueInterest();\n        return totalBorrows;\n    }\n\n    /**\n     * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n     * @param account The address whose balance should be calculated after updating borrowIndex\n     * @return The calculated balance\n     */\n    function borrowBalanceCurrent(address account) override external nonReentrant returns (uint) {\n        accrueInterest();\n        return borrowBalanceStored(account);\n    }\n\n    /**\n     * @notice Return the borrow balance of account based on stored data\n     * @param account The address whose balance should be calculated\n     * @return The calculated balance\n     */\n    function borrowBalanceStored(address account) override public view returns (uint) {\n        return borrowBalanceStoredInternal(account);\n    }\n\n    /**\n     * @notice Return the borrow balance of account based on stored data\n     * @param account The address whose balance should be calculated\n     * @return (error code, the calculated balance or 0 if error code is non-zero)\n     */\n    function borrowBalanceStoredInternal(address account) virtual internal view returns (uint) {\n        /* Get borrowBalance and borrowIndex */\n        BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\n\n        /* If borrowBalance = 0 then borrowIndex is likely also 0.\n         * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n         */\n        if (borrowSnapshot.principal == 0) {\n            return 0;\n        }\n\n        /* Calculate new borrow balance using the interest index:\n         *  recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n         */\n        uint principalTimesIndex = borrowSnapshot.principal * borrowIndex;\n        return principalTimesIndex / borrowSnapshot.interestIndex;\n    }\n\n    /**\n     * @notice Accrue interest then return the up-to-date exchange rate\n     * @return Calculated exchange rate scaled by 1e18\n     */\n    function exchangeRateCurrent() override public nonReentrant returns (uint) {\n        accrueInterest();\n        return exchangeRateStored();\n    }\n\n    /**\n     * @notice Calculates the exchange rate from the underlying to the CToken\n     * @dev This function does not accrue interest before calculating the exchange rate\n     * @return Calculated exchange rate scaled by 1e18\n     */\n    function exchangeRateStored() override public view returns (uint) {\n        return exchangeRateStoredInternal();\n    }\n\n    /**\n     * @notice Calculates the exchange rate from the underlying to the CToken\n     * @dev This function does not accrue interest before calculating the exchange rate\n     * @return calculated exchange rate scaled by 1e18\n     */\n    function exchangeRateStoredInternal() virtual internal view returns (uint) {\n        uint _totalSupply = totalSupply;\n        if (_totalSupply == 0) {\n            /*\n             * If there are no tokens minted:\n             *  exchangeRate = initialExchangeRate\n             */\n            return initialExchangeRateMantissa;\n        } else {\n            /*\n             * Otherwise:\n             *  exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\n             */\n            uint totalCash = getCashPrior();\n            uint cashPlusBorrowsMinusReserves = totalCash + totalBorrows - totalReserves;\n            uint exchangeRate = cashPlusBorrowsMinusReserves * expScale / _totalSupply;\n\n            return exchangeRate;\n        }\n    }\n\n    /**\n     * @notice Get cash balance of this cToken in the underlying asset\n     * @return The quantity of underlying asset owned by this contract\n     */\n    function getCash() override external view returns (uint) {\n        return getCashPrior();\n    }\n\n    /**\n     * @notice Applies accrued interest to total borrows and reserves\n     * @dev This calculates interest accrued from the last checkpointed block\n     *   up to the current block and writes new checkpoint to storage.\n     */\n    function accrueInterest() virtual override public returns (uint) {\n        /* Remember the initial block number */\n        uint currentBlockNumber = getBlockNumber();\n        uint accrualBlockNumberPrior = accrualBlockNumber;\n\n        /* Short-circuit accumulating 0 interest */\n        if (accrualBlockNumberPrior == currentBlockNumber) {\n            return NO_ERROR;\n        }\n\n        /* Read the previous values out of storage */\n        uint cashPrior = getCashPrior();\n        uint borrowsPrior = totalBorrows;\n        uint reservesPrior = totalReserves;\n        uint borrowIndexPrior = borrowIndex;\n\n        /* Calculate the current borrow interest rate */\n        uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n        if (borrowRateMantissa > borrowRateMaxMantissa) {\n            revert BorrowRateIsAbsurdlyHigh(borrowRateMantissa);\n        }\n\n        /* Calculate the number of blocks elapsed since the last accrual */\n        uint blockDelta = currentBlockNumber - accrualBlockNumberPrior;\n\n        /*\n         * Calculate the interest accumulated into borrows and reserves and the new index:\n         *  simpleInterestFactor = borrowRate * blockDelta\n         *  interestAccumulated = simpleInterestFactor * totalBorrows\n         *  totalBorrowsNew = interestAccumulated + totalBorrows\n         *  totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n         *  borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n         */\n\n        Exp memory simpleInterestFactor = mul_(Exp({mantissa: borrowRateMantissa}), blockDelta);\n        uint interestAccumulated = mul_ScalarTruncate(simpleInterestFactor, borrowsPrior);\n        uint totalBorrowsNew = interestAccumulated + borrowsPrior;\n        uint totalReservesNew = mul_ScalarTruncateAddUInt(Exp({mantissa: reserveFactorMantissa}), interestAccumulated, reservesPrior);\n        uint borrowIndexNew = mul_ScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n        /* We write the previously calculated values into storage */\n        accrualBlockNumber = currentBlockNumber;\n        borrowIndex = borrowIndexNew;\n        totalBorrows = totalBorrowsNew;\n        totalReserves = totalReservesNew;\n\n        /* We emit an AccrueInterest event */\n        emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice Sender supplies assets into the market and receives cTokens in exchange\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\n     * @param mintAmount The amount of the underlying asset to supply\n     */\n    function mintInternal(uint mintAmount) internal nonReentrantWL {\n        accrueInterest();\n        // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n        mintFresh(msg.sender, mintAmount);\n    }\n\n    /**\n     * @notice User supplies assets into the market and receives cTokens in exchange\n     * @dev Assumes interest has already been accrued up to the current block\n     * @param minter The address of the account which is supplying the assets\n     * @param mintAmount The amount of the underlying asset to supply\n     */\n    function mintFresh(address minter, uint mintAmount) internal {\n        /* Fail if mint not allowed */\n        uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\n        if (allowed != 0) {\n            revert MintComptrollerRejection(allowed);\n        }\n\n        /* Verify market's block number equals current block number */\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert MintFreshnessCheck();\n        }\n\n        Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()});\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n        /*\n         *  We call `doTransferIn` for the minter and the mintAmount.\n         *  Note: The cToken must handle variations between ERC-20 and ETH underlying.\n         *  `doTransferIn` reverts if anything goes wrong, since we can't be sure if\n         *  side-effects occurred. The function returns the amount actually transferred,\n         *  in case of a fee. On success, the cToken holds an additional `actualMintAmount`\n         *  of cash.\n         */\n        uint actualMintAmount = doTransferIn(minter, mintAmount);\n\n        /*\n         * We get the current exchange rate and calculate the number of cTokens to be minted:\n         *  mintTokens = actualMintAmount / exchangeRate\n         */\n\n        uint mintTokens = div_(actualMintAmount, exchangeRate);\n\n        /*\n         * We calculate the new total supply of cTokens and minter token balance, checking for overflow:\n         *  totalSupplyNew = totalSupply + mintTokens\n         *  accountTokensNew = accountTokens[minter] + mintTokens\n         * And write them into storage\n         */\n        totalSupply = totalSupply + mintTokens;\n        accountTokens[minter] = accountTokens[minter] + mintTokens;\n\n        /* We emit a Mint event, and a Transfer event */\n        emit Mint(minter, actualMintAmount, mintTokens);\n        emit Transfer(address(this), minter, mintTokens);\n    }\n\n    /**\n     * @notice Sender redeems cTokens in exchange for the underlying asset\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\n     * @param redeemTokens The number of cTokens to redeem into underlying\n     */\n    function redeemInternal(uint redeemTokens) internal nonReentrantWL {\n        accrueInterest();\n        // redeemFresh emits redeem-specific logs on errors, so we don't need to\n        redeemFresh(payable(msg.sender), redeemTokens, 0);\n    }\n\n    /**\n     * @notice Sender redeems cTokens in exchange for a specified amount of underlying asset\n     * @dev Accrues interest whether or not the operation succeeds, unless reverted\n     * @param redeemAmount The amount of underlying to receive from redeeming cTokens\n     */\n    function redeemUnderlyingInternal(uint redeemAmount) internal nonReentrantWL {\n        accrueInterest();\n        // redeemFresh emits redeem-specific logs on errors, so we don't need to\n        redeemFresh(payable(msg.sender), 0, redeemAmount);\n    }\n\n    /**\n     * @notice User redeems cTokens in exchange for the underlying asset\n     * @dev Assumes interest has already been accrued up to the current block\n     * @param redeemer The address of the account which is redeeming the tokens\n     * @param redeemTokensIn The number of cTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n     * @param redeemAmountIn The number of underlying tokens to receive from redeeming cTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n     */\n    function redeemFresh(address payable redeemer, uint redeemTokensIn, uint redeemAmountIn) internal virtual {\n        // Fail if both redeemTokensIn and redeemAmountIn are non-zero\n        if (redeemTokensIn != 0 && redeemAmountIn != 0) {\n            revert RedeemInvalidInputs();\n        }\n\n        /* exchangeRate = invoke Exchange Rate Stored() */\n        Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal() });\n\n        uint redeemTokens;\n        uint redeemAmount;\n        /* If redeemTokensIn > 0: */\n        if (redeemTokensIn > 0) {\n            /*\n             * We calculate the exchange rate and the amount of underlying to be redeemed:\n             *  redeemTokens = redeemTokensIn\n             *  redeemAmount = redeemTokensIn x exchangeRateCurrent\n             */\n            redeemTokens = redeemTokensIn;\n            redeemAmount = mul_ScalarTruncate(exchangeRate, redeemTokensIn);\n        } else {\n            /*\n             * We get the current exchange rate and calculate the amount to be redeemed:\n             *  redeemTokens = redeemAmountIn / exchangeRate\n             *  redeemAmount = redeemAmountIn\n             */\n            redeemTokens = div_(redeemAmountIn, exchangeRate);\n            redeemAmount = redeemAmountIn;\n        }\n\n        /* Fail if redeem not allowed */\n        uint allowed = comptroller.redeemAllowed(address(this), redeemer, redeemTokens);\n        if (allowed != 0) {\n            revert RedeemComptrollerRejection(allowed);\n        }\n\n        /* Verify market's block number equals current block number */\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert RedeemFreshnessCheck();\n        }\n\n        /* Fail gracefully if protocol has insufficient cash */\n        if (getCashPrior() < redeemAmount) {\n            revert RedeemTransferOutNotPossible();\n        }\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n\n        /*\n         * We write the previously calculated values into storage.\n         *  Note: Avoid token reentrancy attacks by writing reduced supply before external transfer.\n         */\n        totalSupply = totalSupply - redeemTokens;\n\n        uint accountTokensNew = accountTokens[redeemer] - redeemTokens;\n        accountTokens[redeemer] = accountTokensNew;\n\n        /*\n         * We invoke doTransferOut for the redeemer and the redeemAmount.\n         *  Note: The cToken must handle variations between ERC-20 and ETH underlying.\n         *  On success, the cToken has redeemAmount less of cash.\n         *  doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n         */\n        doTransferOut(redeemer, redeemAmount);\n\n        /* We emit a Transfer event, and a Redeem event */\n        emit Transfer(redeemer, address(this), redeemTokens);\n        emit Redeem(redeemer, redeemAmount, redeemTokens);\n\n        // Require tokens is zero or amount is also zero (defense check)\n        if (redeemTokens == 0 && redeemAmount > 0) {\n            revert(\"redeemTokens zero\");\n        }\n\n        if (accountTokensNew == 0 && borrowBalanceStoredInternal(redeemer) == 0) {\n            comptroller.autoExitMarkets(redeemer); // silent failure allowed\n        }\n    }\n\n    /**\n      * @notice Sender borrows assets from the protocol to their own address\n      * @param borrowAmount The amount of the underlying asset to borrow\n      */\n    function borrowInternal(uint borrowAmount) internal nonReentrantWL {\n        accrueInterest();\n        // borrowFresh emits borrow-specific logs on errors, so we don't need to\n        borrowFresh(payable(msg.sender), borrowAmount);\n    }\n\n    /**\n      * @notice Users borrow assets from the protocol to their own address\n      * @param borrowAmount The amount of the underlying asset to borrow\n      */\n    function borrowFresh(address payable borrower, uint borrowAmount) internal virtual {\n        /* Fail if borrow not allowed */\n        uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\n        if (allowed != 0) {\n            revert BorrowComptrollerRejection(allowed);\n        }\n\n        /* Verify market's block number equals current block number */\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert BorrowFreshnessCheck();\n        }\n\n        /* Fail gracefully if protocol has insufficient underlying cash */\n        if (getCashPrior() < borrowAmount) {\n            revert BorrowCashNotAvailable();\n        }\n\n        /*\n         * We calculate the new borrower and total borrow balances, failing on overflow:\n         *  accountBorrowNew = accountBorrow + borrowAmount\n         *  totalBorrowsNew = totalBorrows + borrowAmount\n         */\n        uint accountBorrowsPrev = borrowBalanceStoredInternal(borrower);\n        uint accountBorrowsNew = accountBorrowsPrev + borrowAmount;\n        uint totalBorrowsNew = totalBorrows + borrowAmount;\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n        /*\n         * We write the previously calculated values into storage.\n         *  Note: Avoid token reentrancy attacks by writing increased borrow before external transfer.\n        `*/\n        accountBorrows[borrower].principal = accountBorrowsNew;\n        accountBorrows[borrower].interestIndex = borrowIndex;\n        totalBorrows = totalBorrowsNew;\n\n        /*\n         * We invoke doTransferOut for the borrower and the borrowAmount.\n         *  Note: The cToken must handle variations between ERC-20 and ETH underlying.\n         *  On success, the cToken borrowAmount less of cash.\n         *  doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n         */\n        doTransferOut(borrower, borrowAmount);\n\n        /* We emit a Borrow event */\n        emit Borrow(borrower, borrowAmount, accountBorrowsNew, totalBorrowsNew);\n    }\n\n    /**\n     * @notice Sender repays their own borrow\n     * @param repayAmount The amount to repay, or -1 for the full outstanding amount\n     */\n    function repayBorrowInternal(uint repayAmount) internal nonReentrantWL {\n        accrueInterest();\n        // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n        repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n    }\n\n    /**\n     * @notice Sender repays a borrow belonging to borrower\n     * @param borrower the account with the debt being payed off\n     * @param repayAmount The amount to repay, or -1 for the full outstanding amount\n     */\n    function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrantWL {\n        accrueInterest();\n        // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n        repayBorrowFresh(msg.sender, borrower, repayAmount);\n    }\n\n    /**\n     * @notice Borrows are repaid by another user (possibly the borrower).\n     * @param payer the account paying off the borrow\n     * @param borrower the account with the debt being payed off\n     * @param repayAmount the amount of underlying tokens being returned, or -1 for the full outstanding amount\n     * @return (uint) the actual repayment amount.\n     */\n    function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal virtual returns (uint) {\n        /* Fail if repayBorrow not allowed */\n        uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\n        if (allowed != 0) {\n            revert RepayBorrowComptrollerRejection(allowed);\n        }\n\n        /* Verify market's block number equals current block number */\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert RepayBorrowFreshnessCheck();\n        }\n\n        /* We fetch the amount the borrower owes, with accumulated interest */\n        uint accountBorrowsPrev = borrowBalanceStoredInternal(borrower);\n\n        /* If repayAmount == -1, repayAmount = accountBorrows */\n        uint repayAmountFinal = repayAmount == type(uint).max ? accountBorrowsPrev : repayAmount;\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n        /*\n         * We call doTransferIn for the payer and the repayAmount\n         *  Note: The cToken must handle variations between ERC-20 and ETH underlying.\n         *  On success, the cToken holds an additional repayAmount of cash.\n         *  doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n         *   it returns the amount actually transferred, in case of a fee.\n         */\n        uint actualRepayAmount = doTransferIn(payer, repayAmountFinal);\n\n        /*\n         * We calculate the new borrower and total borrow balances, failing on underflow:\n         *  accountBorrowsNew = accountBorrows - actualRepayAmount\n         *  totalBorrowsNew = totalBorrows - actualRepayAmount\n         */\n        uint accountBorrowsNew = accountBorrowsPrev - actualRepayAmount;\n        uint totalBorrowsNew = totalBorrows > actualRepayAmount ? totalBorrows - actualRepayAmount : 0;\n\n        /* We write the previously calculated values into storage */\n        accountBorrows[borrower].principal = accountBorrowsNew;\n        accountBorrows[borrower].interestIndex = borrowIndex;\n        totalBorrows = totalBorrowsNew;\n\n        /* We emit a RepayBorrow event */\n        emit RepayBorrow(payer, borrower, actualRepayAmount, accountBorrowsNew, totalBorrowsNew);\n\n        if (accountBorrowsNew == 0 && accountTokens[borrower] == 0) {\n            comptroller.autoExitMarkets(borrower); // silent failure allowed\n        }\n\n        return actualRepayAmount;\n    }\n\n    /**\n     * @notice The sender liquidates the borrowers collateral.\n     *  The collateral seized is transferred to the liquidator.\n     * @param liquidator The liquidator repaying the borrow and seizing collateral\n     * @param borrower The borrower of this cToken to be liquidated\n     * @param repayAmount The amount of the underlying borrowed asset to repay\n     */\n    function _liquidateBorrowInternal(address liquidator, address borrower, uint repayAmount) internal nonReentrant returns (uint) {\n        if (msg.sender != address(comptroller)) {\n            revert Unauthorized();\n        }\n\n        accrueInterest();\n\n        /* Verify market's block number equals current block number */\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert LiquidateFreshnessCheck();\n        }\n\n        /* Fail if borrower = liquidator */\n        if (borrower == liquidator) {\n            revert LiquidateLiquidatorIsBorrower();\n        }\n\n        /* Fail if repayAmount = 0 */\n        if (repayAmount == 0) {\n            revert LiquidateCloseAmountIsZero();\n        }\n\n        /* Fail if repayBorrow fails */\n        uint actualRepayAmount = repayBorrowFresh(liquidator, borrower, repayAmount);\n\n        /* We emit a LiquidateBorrow event */\n        emit LiquidateBorrow(liquidator, borrower, actualRepayAmount);\n\n        return actualRepayAmount;\n    }\n\n    /**\n     * @notice Transfers collateral tokens (this market) to the liquidator.\n     *         This function can only be called by the Comptroller.\n     * @param liquidator The account receiving seized collateral\n     * @param borrower The account having collateral seized\n     * @param seizeTokens The number of cTokens to seize\n     * @return uint actual seizeTokens\n     */\n    function _seize(address liquidator, address borrower, uint seizeTokens) override virtual external nonReentrant returns (uint) {\n        if (msg.sender != address(comptroller)) {\n            revert Unauthorized();\n        }\n\n        accrueInterest();\n\n        /* Fail if borrower = liquidator */\n        if (borrower == liquidator) {\n            revert LiquidateSeizeLiquidatorIsBorrower();\n        }\n\n        /*\n         * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\n         *  borrowerTokensNew = accountTokens[borrower] - seizeTokens\n         *  liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\n         */\n        uint protocolSeizeTokens = mul_(seizeTokens, Exp({mantissa: protocolSeizeShareMantissa}));\n        uint liquidatorSeizeTokens = seizeTokens - protocolSeizeTokens;\n        Exp memory exchangeRate = Exp({mantissa: exchangeRateStoredInternal()});\n        uint protocolSeizeAmount = mul_ScalarTruncate(exchangeRate, protocolSeizeTokens);\n        uint totalReservesNew = totalReserves + protocolSeizeAmount;\n\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n        /* We write the calculated values into storage */\n        totalReserves = totalReservesNew;\n        totalSupply = totalSupply - protocolSeizeTokens;\n        accountTokens[borrower] = accountTokens[borrower] - seizeTokens;\n        accountTokens[liquidator] = accountTokens[liquidator] + liquidatorSeizeTokens;\n\n        /* Emit a Transfer event */\n        emit Transfer(borrower, liquidator, liquidatorSeizeTokens);\n        emit Transfer(borrower, address(this), protocolSeizeTokens);\n        emit ReservesAdded(address(this), protocolSeizeAmount, totalReservesNew);\n\n        return seizeTokens;\n    }\n\n    /*** Admin Functions ***/\n\n    /**\n      * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n      * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n      * @param newPendingAdmin New pending admin.\n      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n      */\n    function _setPendingAdmin(address payable newPendingAdmin) override external returns (uint) {\n        // Check caller = admin\n        if (msg.sender != admin) {\n            revert SetPendingAdminOwnerCheck();\n        }\n\n        // Save current value, if any, for inclusion in log\n        address oldPendingAdmin = pendingAdmin;\n\n        // Store pendingAdmin with value newPendingAdmin\n        pendingAdmin = newPendingAdmin;\n\n        // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n        emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n        return NO_ERROR;\n    }\n\n    /**\n      * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n      * @dev Admin function for pending admin to accept role and update admin\n      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n      */\n    function _acceptAdmin() override external returns (uint) {\n        // Check caller is pendingAdmin and pendingAdmin â‰  address(0)\n        if (msg.sender != pendingAdmin || msg.sender == address(0)) {\n            revert AcceptAdminPendingAdminCheck();\n        }\n\n        // Save current values for inclusion in log\n        address oldAdmin = admin;\n        address oldPendingAdmin = pendingAdmin;\n\n        // Store admin with value pendingAdmin\n        admin = pendingAdmin;\n\n        // Clear the pending value\n        pendingAdmin = payable(address(0));\n\n        emit NewAdmin(oldAdmin, admin);\n        emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n        return NO_ERROR;\n    }\n\n    /**\n      * @notice Sets a new comptroller for the market\n      * @dev Admin function to set a new comptroller\n      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n      */\n    function _setComptroller(ComptrollerInterface newComptroller) override public returns (uint) {\n        // Check caller is admin\n        if (msg.sender != admin) {\n            revert SetComptrollerOwnerCheck();\n        }\n\n        ComptrollerInterface oldComptroller = comptroller;\n        // Ensure invoke comptroller.isComptroller() returns true\n        if (!newComptroller.isComptroller()) {\n            revert InvalidComptrollerAddress(address(newComptroller));\n        }\n\n        // Set market's comptroller to newComptroller\n        comptroller = newComptroller;\n\n        // Emit NewComptroller(oldComptroller, newComptroller)\n        emit NewComptroller(oldComptroller, newComptroller);\n\n        return NO_ERROR;\n    }\n\n    /**\n      * @notice Sets protocolSeizeShareMantissa\n      * @dev Admin function to set protocolSeizeShareMantissa\n      * @param newProtocolSeizeShareMantissa New protocolSeizeShareMantissa scaled by 1e18\n      * @return uint 0=success, otherwise a failure. (See ErrorReporter for details)\n      */\n    function _setProtocolSeizeShare(uint newProtocolSeizeShareMantissa) virtual override external returns (uint) {\n        // Check caller is admin\n        if (msg.sender != admin) {\n            revert SetProtocolSeizeShareAdminCheck();\n        }\n\n        if (newProtocolSeizeShareMantissa > protocolSeizeShareMaxMantissa) {\n            revert SetProtocolSeizeShareTooHigh();\n        }\n\n        // Save current value for use in log\n        uint oldProtocolSeizeShareMantissa = protocolSeizeShareMantissa;\n\n        // Set liquidation incentive to new incentive\n        protocolSeizeShareMantissa = newProtocolSeizeShareMantissa;\n\n        // Emit event with old incentive, new incentive\n        emit NewProtocolSeizeShare(oldProtocolSeizeShareMantissa, newProtocolSeizeShareMantissa);\n\n        return NO_ERROR;\n    }\n\n    /**\n      * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n      * @dev Admin function to accrue interest and set a new reserve factor\n      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n      */\n    function _setReserveFactor(uint newReserveFactorMantissa) override external nonReentrant returns (uint) {\n        accrueInterest();\n        // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\n        return _setReserveFactorFresh(newReserveFactorMantissa);\n    }\n\n    /**\n      * @notice Sets a new reserve factor for the protocol (*requires fresh interest accrual)\n      * @dev Admin function to set a new reserve factor\n      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n      */\n    function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\n        // Check caller is admin\n        if (msg.sender != admin) {\n            revert SetReserveFactorAdminCheck();\n        }\n\n        // Verify market's block number equals current block number\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert SetReserveFactorFreshCheck();\n        }\n\n        // Check newReserveFactor â‰¤ maxReserveFactor\n        if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\n            revert SetReserveFactorBoundsCheck();\n        }\n\n        uint oldReserveFactorMantissa = reserveFactorMantissa;\n        reserveFactorMantissa = newReserveFactorMantissa;\n\n        emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice Accrues interest and reduces reserves by transferring from msg.sender\n     * @param addAmount Amount of addition to reserves\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _addReservesInternal(uint addAmount) internal nonReentrantWL returns (uint) {\n        accrueInterest();\n\n        // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\n        _addReservesFresh(addAmount);\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice Add reserves by transferring from caller\n     * @dev Requires fresh interest accrual\n     * @param addAmount Amount of addition to reserves\n     * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\n     */\n    function _addReservesFresh(uint addAmount) internal virtual returns (uint, uint) {\n        // totalReserves + actualAddAmount\n        uint totalReservesNew;\n        uint actualAddAmount = 0;\n\n        // We fail gracefully unless market's block number equals current block number\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert AddReservesFactorFreshCheck(actualAddAmount);\n        }\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n        /*\n         * We call doTransferIn for the caller and the addAmount\n         *  Note: The cToken must handle variations between ERC-20 and ETH underlying.\n         *  On success, the cToken holds an additional addAmount of cash.\n         *  doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n         *  it returns the amount actually transferred, in case of a fee.\n         */\n\n        actualAddAmount = doTransferIn(msg.sender, addAmount);\n\n        totalReservesNew = totalReserves + actualAddAmount;\n\n        // Store reserves[n+1] = reserves[n] + actualAddAmount\n        totalReserves = totalReservesNew;\n\n        /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\n        emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n        /* Return (NO_ERROR, actualAddAmount) */\n        return (NO_ERROR, actualAddAmount);\n    }\n\n\n    /**\n     * @notice Accrues interest and reduces reserves by transferring to admin\n     * @param reduceAmount Amount of reduction to reserves\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _reduceReserves(uint reduceAmount) override external nonReentrant returns (uint) {\n        accrueInterest();\n        // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\n        return _reduceReservesFresh(reduceAmount);\n    }\n\n    /**\n     * @notice Reduces reserves by transferring to admin\n     * @dev Requires fresh interest accrual\n     * @param reduceAmount Amount of reduction to reserves\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\n        // totalReserves - reduceAmount\n        uint totalReservesNew;\n\n        // Check caller is admin\n        if (msg.sender != admin) {\n            revert ReduceReservesAdminCheck();\n        }\n\n        // We fail gracefully unless market's block number equals current block number\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert ReduceReservesFreshCheck();\n        }\n\n        // Fail gracefully if protocol has insufficient underlying cash\n        if (getCashPrior() < reduceAmount) {\n            revert ReduceReservesCashNotAvailable();\n        }\n\n        // Check reduceAmount â‰¤ reserves[n] (totalReserves)\n        if (reduceAmount > totalReserves) {\n            revert ReduceReservesCashValidation();\n        }\n\n        /////////////////////////\n        // EFFECTS & INTERACTIONS\n        // (No safe failures beyond this point)\n\n        totalReservesNew = totalReserves - reduceAmount;\n\n        // Store reserves[n+1] = reserves[n] - reduceAmount\n        totalReserves = totalReservesNew;\n\n        // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n        doTransferOut(admin, reduceAmount);\n\n        emit ReservesReduced(admin, reduceAmount, totalReservesNew);\n\n        return NO_ERROR;\n    }\n\n    /**\n     * @notice accrues interest and updates the interest rate model using _setInterestRateModelFresh\n     * @dev Admin function to accrue interest and update the interest rate model\n     * @param newInterestRateModel the new interest rate model to use\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _setInterestRateModel(InterestRateModel newInterestRateModel) override public returns (uint) {\n        accrueInterest();\n        // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\n        return _setInterestRateModelFresh(newInterestRateModel);\n    }\n\n    /**\n     * @notice updates the interest rate model (*requires fresh interest accrual)\n     * @dev Admin function to update the interest rate model\n     * @param newInterestRateModel the new interest rate model to use\n     * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n     */\n    function _setInterestRateModelFresh(InterestRateModel newInterestRateModel) internal returns (uint) {\n\n        // Used to store old model for use in the event that is emitted on success\n        InterestRateModel oldInterestRateModel;\n\n        // Check caller is admin\n        if (msg.sender != admin) {\n            revert SetInterestRateModelOwnerCheck();\n        }\n\n        // We fail gracefully unless market's block number equals current block number\n        if (accrualBlockNumber != getBlockNumber()) {\n            revert SetInterestRateModelFreshCheck();\n        }\n\n        // Track the market's current interest rate model\n        oldInterestRateModel = interestRateModel;\n\n        // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n        if (!newInterestRateModel.isInterestRateModel()) {\n            revert InvalidRateModelAddress(address(newInterestRateModel));\n        }\n\n        // Set the interest rate model to newInterestRateModel\n        interestRateModel = newInterestRateModel;\n\n        // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n        emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\n\n        return NO_ERROR;\n    }\n\n    function _ensureNonEmpty(address minter, uint amount) virtual external;\n\n    // called only once by the comptroller during _supportMarket\n    function _ensureNonEmptyInternal(address minter, uint amount) internal nonReentrant {\n        if (msg.sender != address(comptroller)) {\n            revert Unauthorized();\n        }\n\n        if (amount == 0) {\n            revert EnsureNonEmptyAmountTooSmall();\n        }\n\n        // this function is called during market setup, so an existing totalSupply should not be possible\n        assert(totalSupply == 0);\n\n        accrueInterest();\n        mintFresh(minter, amount);\n\n        uint totalSupply_ = totalSupply;\n        if (totalSupply_ == 0) {\n            revert EnsureNonEmptyAmountTooSmall();\n        }\n        assert(totalSupply_ == accountTokens[minter]);\n\n        // burn minted balance\n        accountTokens[minter] = 0;\n        accountTokens[address(0)] = totalSupply_;\n        emit Transfer(minter, address(0), totalSupply_);\n    }\n\n    /*** Safe Token ***/\n\n    /**\n     * @notice Gets balance of this contract in terms of the underlying\n     * @dev This excludes the value of the current message, if any\n     * @return The quantity of underlying owned by this contract\n     */\n    function getCashPrior() virtual internal view returns (uint);\n\n    /**\n     * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\n     *  This may revert due to insufficient balance or insufficient allowance.\n     */\n    function doTransferIn(address from, uint amount) virtual internal returns (uint);\n\n    /**\n     * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\n     *  If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\n     *  If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\n     */\n    function doTransferOut(address payable to, uint amount) virtual internal;\n\n\n    /*** Reentrancy Guard ***/\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     */\n    modifier nonReentrant() {\n        if (!_notEntered) {\n            revert Reentry();\n        }\n        _notEntered = false;\n        _;\n        _notEntered = true; // get a gas-refund post-Istanbul\n    }\n\n    modifier nonReentrantWL() {\n        if (!comptroller._checkEoaOrWL(msg.sender)) {\n            revert Unauthorized();\n        }\n        if (!_notEntered) {\n            revert Reentry();\n        }\n        _notEntered = false;\n        _;\n        _notEntered = true; // get a gas-refund post-Istanbul\n    }\n}\n"
      },
      "contracts/ComptrollerInterface.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\nabstract contract ComptrollerInterface {\n    /// @notice Indicator that this is a Comptroller contract (for inspection)\n    bool public constant isComptroller = true;\n\n    /*** Assets You Are In ***/\n\n    function autoEnterMarkets(address account) virtual external;\n    function autoExitMarkets(address account) virtual external;\n    function enterMarkets(address[] calldata cTokens) virtual external returns (uint[] memory);\n    function exitMarket(address cToken) virtual external returns (uint);\n    function redeemAllInterest(address lender, address[] memory cTokens) virtual external returns (uint[] memory);\n\n    /*** Policy Hooks ***/\n\n    function mintAllowed(address cToken, address minter, uint mintAmount) virtual external returns (uint);\n\n    function redeemAllowed(address cToken, address redeemer, uint redeemTokens) virtual external returns (uint);\n\n    function borrowAllowed(address cToken, address borrower, uint borrowAmount) virtual external returns (uint);\n\n    function repayBorrowAllowed(\n        address cToken,\n        address payer,\n        address borrower,\n        uint repayAmount) virtual external returns (uint);\n\n    function collectInterestAllowed(\n        address cTokenInterestMarket,\n        address cTokenSupplyMarket,\n        address lender,\n        uint interestAmount) virtual external returns (uint);\n\n    function payInterestAllowed(\n        address cTokenInterestMarket,\n        address cTokenBorrowMarket,\n        address payer,\n        uint payTokens) virtual external returns (uint);\n\n    function transferAllowed(address cToken, address src, address dst, uint transferTokens) virtual external returns (uint);\n\n    function isListed(address cToken) virtual external view returns (bool);\n\n    function getAssetsExchangeRate(address cTokenA, address cTokenB) virtual external view returns (uint);\n\n    function _checkEoaOrWL(address msgSender) virtual external view returns (bool);\n\n    /*** Liquidity/Liquidation Calculations ***/\n\n    struct Liquidatables {\n        address cToken; // token to liquidate\n        uint amount;    // non-NFT markets\n        uint[] nftIds;  // NFT markets\n    }\n\n    function topUpInterestShortfall(address borrower, uint maxTopUpTokens, address cTokenCollateral) virtual external returns (uint[2] memory);\n\n    function batchLiquidateBorrow(address borrower, Liquidatables[] memory liquidatables, address[] memory cTokenCollaterals, uint minSeizedValue) virtual external returns (uint[][2] memory results);\n\n    function liquidateCalculateSeizeTokensNormed(address cTokenCollateral, uint normedRepayAmount) virtual public view returns (uint);\n\n    function interestMarket() virtual external view returns (address);\n}\n"
      },
      "contracts/CTokenInterfaces.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\nimport \"contracts/ComptrollerInterface.sol\";\nimport \"contracts/InterestRateModel.sol\";\nimport \"contracts/EIP20NonStandardInterface.sol\";\nimport \"contracts/ErrorReporter.sol\";\n\ncontract CTokenStorage {\n    /**\n     * @dev Guard variable for re-entrancy checks\n     */\n    bool internal _notEntered;\n\n    /**\n     * @notice EIP-20 token name for this token\n     */\n    string public name;\n\n    /**\n     * @notice EIP-20 token symbol for this token\n     */\n    string public symbol;\n\n    /**\n     * @notice EIP-20 token decimals for this token\n     */\n    uint8 public decimals;\n\n    // Maximum borrow rate that can ever be applied (.0005% / block)\n    uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n    // Maximum fraction of interest that can be set aside for reserves\n    uint internal constant reserveFactorMaxMantissa = 1e18;\n\n    // Maximum protocol seize share that can be set\n    uint internal constant protocolSeizeShareMaxMantissa = 20e16;\n\n    /**\n     * @notice Administrator for this contract\n     */\n    address payable public admin;\n\n    /**\n     * @notice Pending administrator for this contract\n     */\n    address payable public pendingAdmin;\n\n    /**\n     * @notice Contract which oversees inter-cToken operations\n     */\n    ComptrollerInterface public comptroller;\n\n    /**\n     * @notice Model which tells what the current interest rate should be\n     */\n    InterestRateModel public interestRateModel;\n\n    // Initial exchange rate used when minting the first CTokens (used when totalSupply = 0)\n    uint internal initialExchangeRateMantissa;\n\n    /**\n     * @notice Fraction of interest currently set aside for reserves\n     */\n    uint public reserveFactorMantissa;\n\n    /**\n     * @notice Block number that interest was last accrued at\n     */\n    uint public accrualBlockNumber;\n\n    /**\n     * @notice Accumulator of the total earned interest rate since the opening of the market\n     */\n    uint public borrowIndex;\n\n    /**\n     * @notice Total amount of outstanding borrows of the underlying in this market\n     */\n    uint public totalBorrows;\n\n    /**\n     * @notice Total amount of reserves of the underlying held in this market\n     */\n    uint public totalReserves;\n\n    /**\n     * @notice Total number of tokens in circulation\n     */\n    uint public totalSupply;\n\n    // Official record of token balances for each account\n    mapping (address => uint) internal accountTokens;\n\n    // Approved token transfer amounts on behalf of others\n    mapping (address => mapping (address => uint)) internal transferAllowances;\n\n    /**\n     * @notice Container for borrow balance information\n     * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\n     * @member interestIndex Global borrowIndex as of the most recent balance-changing action\n     * @member interestAccrued Total interest accrued for markets that track it separately from borrow balance\n     */\n    struct BorrowSnapshot {\n        uint principal;\n        uint interestIndex;\n        uint interestAccrued;\n    }\n\n    // Mapping of account addresses to outstanding borrow balances\n    mapping(address => BorrowSnapshot) internal accountBorrows;\n\n    /**\n     * @notice Share of seized collateral that is added to reserves\n     */\n    uint public protocolSeizeShareMantissa = 2.8e16; //2.8%\n\n    /**\n     * @notice MarketType enum\n     */\n    enum MarketType {\n        UNDEFINED_MARKET,\n        ERC20_MARKET,\n        ERC721_MARKET,\n        ERC20_INTEREST_MARKET\n    }\n\n    /**\n     * @notice Indicates a token market type\n     */\n    MarketType public marketType;\n}\n\nabstract contract CTokenInterface is CTokenStorage {\n    /**\n     * @notice Indicator that this is a CToken contract (for inspection)\n     */\n    bool public constant isCToken = true;\n\n\n    /*** Market Events ***/\n\n    /**\n     * @notice Event emitted when interest is accrued\n     */\n    event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\n\n    /**\n     * @notice Event emitted when tokens are minted\n     */\n    event Mint(address minter, uint mintAmount, uint mintTokens);\n\n    /**\n     * @notice Event emitted when tokens are redeemed\n     */\n    event Redeem(address redeemer, uint redeemAmount, uint redeemTokens);\n\n    /**\n     * @notice Event emitted when underlying is borrowed\n     */\n    event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\n\n    /**\n     * @notice Event emitted when a borrow is repaid\n     */\n    event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\n\n    /**\n     * @notice Event emitted when a borrow is liquidated\n     */\n    event LiquidateBorrow(address liquidator, address borrower, uint repayAmount);\n\n\n    /*** Admin Events ***/\n\n    /**\n     * @notice Event emitted when pendingAdmin is changed\n     */\n    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n    /**\n     * @notice Event emitted when pendingAdmin is accepted, which means admin is updated\n     */\n    event NewAdmin(address oldAdmin, address newAdmin);\n\n    /**\n     * @notice Event emitted when comptroller is changed\n     */\n    event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\n\n    /**\n     * @notice Event emitted when interestRateModel is changed\n     */\n    event NewMarketInterestRateModel(InterestRateModel oldInterestRateModel, InterestRateModel newInterestRateModel);\n\n    /**\n     * @notice Event emitted when the seize share is changed\n     */\n    event NewProtocolSeizeShare(uint oldProtocolSeizeShareMantissa, uint newProtocolSeizeShareMantissa);\n\n    /**\n     * @notice Event emitted when the reserve factor is changed\n     */\n    event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\n\n    /**\n     * @notice Event emitted when the reserves are added\n     */\n    event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\n\n    /**\n     * @notice Event emitted when the reserves are reduced\n     */\n    event ReservesReduced(address admin, uint reduceAmount, uint newTotalReserves);\n\n    /**\n     * @notice EIP20 Transfer event\n     */\n    event Transfer(address indexed from, address indexed to, uint amount);\n\n    /**\n     * @notice EIP20 Approval event\n     */\n    event Approval(address indexed owner, address indexed spender, uint amount);\n\n\n    /*** User Interface ***/\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    function approve(address spender, uint amount) virtual external returns (bool);\n    function allowance(address owner, address spender) virtual external view returns (uint);\n    function balanceOf(address owner) virtual external view returns (uint);\n    function balanceOfUnderlying(address owner) virtual external returns (uint);\n    function getAccountSnapshot(address account) virtual external view returns (uint, uint, uint, uint, uint);\n    function borrowRatePerBlock() virtual external view returns (uint);\n    function supplyRatePerBlock() virtual external view returns (uint);\n    function totalBorrowsCurrent() virtual external returns (uint);\n    function borrowBalanceCurrent(address account) virtual external returns (uint);\n    function borrowBalanceStored(address account) virtual external view returns (uint);\n    function exchangeRateCurrent() virtual external returns (uint);\n    function exchangeRateStored() virtual external view returns (uint);\n    function getCash() virtual external view returns (uint);\n    function accrueInterest() virtual external returns (uint);\n    function _seize(address liquidator, address borrower, uint seizeTokens) virtual external returns (uint);\n    function sweepToken(EIP20NonStandardInterface token) virtual external;\n\n\n    /*** Admin Functions ***/\n\n    function _setPendingAdmin(address payable newPendingAdmin) virtual external returns (uint);\n    function _acceptAdmin() virtual external returns (uint);\n    function _setComptroller(ComptrollerInterface newComptroller) virtual external returns (uint);\n    function _setProtocolSeizeShare(uint newProtocolSeizeShareMantissa) virtual external returns (uint);\n    function _setReserveFactor(uint newReserveFactorMantissa) virtual external returns (uint);\n    function _reduceReserves(uint reduceAmount) virtual external returns (uint);\n    function _setInterestRateModel(InterestRateModel newInterestRateModel) virtual external returns (uint);\n}\n\ncontract CErc20Storage {\n    /**\n     * @notice Underlying asset for this CToken\n     */\n    address public underlying;\n}\n\nabstract contract CErc20Interface is CErc20Storage {\n\n    /*** User Interface ***/\n\n    function mint(uint mintAmount) virtual external returns (uint);\n    function redeem(uint redeemTokens) virtual external returns (uint);\n    function redeemUnderlying(uint redeemAmount) virtual external returns (uint);\n    function borrow(uint borrowAmount) virtual external returns (uint);\n    function repayBorrow(uint repayAmount) virtual external returns (uint);\n    function repayBorrowBehalf(address borrower, uint repayAmount) virtual external returns (uint);\n    function _liquidateBorrow(address liquidator, address borrower, uint repayAmount) virtual external returns (uint);\n\n    /*** Admin Functions ***/\n\n    function _addReserves(uint addAmount) virtual external returns (uint);\n}\n\ninterface IWeth {\n    function transferFrom(address src, address dst, uint wad) external;\n    function withdraw(uint256 wad) external;\n}\n\nabstract contract CEtherInterface is CErc20Storage {\n\n    /*** User Interface ***/\n\n    function mint() virtual external payable;\n    function redeem(uint redeemTokens) virtual external returns (uint);\n    function redeemUnderlying(uint redeemAmount) virtual external returns (uint);\n    function borrow(uint borrowAmount) virtual external returns (uint);\n    function repayBorrow() virtual external payable;\n    function repayBorrowBehalf(address borrower) virtual external payable;\n    function _liquidateBorrow(address liquidator, address borrower, uint repayAmount) virtual external returns (uint);\n\n    /*** Admin Functions ***/\n\n    function _addReserves() virtual external payable returns (uint);\n}\n\ncontract CDelegationStorage {\n    /**\n     * @notice Implementation address for this contract\n     */\n    address public implementation;\n}\n\nabstract contract CDelegatorInterface is CDelegationStorage {\n    /**\n     * @notice Emitted when implementation is changed\n     */\n    event NewImplementation(address oldImplementation, address newImplementation);\n\n    error CannotReceiveValueGtZero();\n\n    /**\n     * @notice Called by the admin to update the implementation of the delegator\n     * @param implementation_ The address of the new implementation for delegation\n     * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n     * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n     */\n    function _setImplementation(address implementation_, bool allowResign, bytes memory becomeImplementationData) virtual external;\n}\n\nabstract contract CDelegateInterface is CDelegationStorage {\n    /**\n     * @notice Called by the delegator on a delegate to initialize it for duty\n     * @dev Should revert if any issues arise which make it unfit for delegation\n     * @param data The encoded bytes data for any initialization\n     */\n    function _becomeImplementation(bytes memory data) virtual external;\n\n    /**\n     * @notice Called by the delegator on a delegate to forfeit its responsibility\n     */\n    function _resignImplementation() virtual external;\n}\n"
      },
      "contracts/InterestRateModel.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\n/**\n  * @title Compound's InterestRateModel Interface\n  * @author Compound\n  */\nabstract contract InterestRateModel {\n    /// @notice Indicator that this is an InterestRateModel contract (for inspection)\n    bool public constant isInterestRateModel = true;\n\n    /**\n      * @notice Calculates the current borrow interest rate per block\n      * @param cash The total amount of cash the market has\n      * @param borrows The total amount of borrows the market has outstanding\n      * @param reserves The total amount of reserves the market has\n      * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n      */\n    function getBorrowRate(uint cash, uint borrows, uint reserves) virtual public view returns (uint);\n\n    /**\n      * @notice Calculates the current supply interest rate per block\n      * @param cash The total amount of cash the market has\n      * @param borrows The total amount of borrows the market has outstanding\n      * @param reserves The total amount of reserves the market has\n      * @param reserveFactorMantissa The current reserve factor the market has\n      * @return The supply rate per block (as a percentage, and scaled by 1e18)\n      */\n    function getSupplyRate(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual public view returns (uint);\n\n    /**\n     * @notice Calculates the current borrow and supply rate per block\n     * @param cash The amount of cash in the market\n     * @param borrows The amount of borrows in the market\n     * @param reserves The amount of reserves in the market\n     * @param reserveFactorMantissa The current reserve factor for the market\n     * @return (uint, uint) The borrow rate percentage per block as a mantissa (scaled by BASE),\n     *         supply rate percentage per block as a mantissa (scaled by BASE)\n     */\n    function getMarketRates(uint cash, uint borrows, uint reserves, uint reserveFactorMantissa) virtual public view returns (uint, uint) {\n      return (getBorrowRate(cash, borrows, reserves), getSupplyRate(cash, borrows, reserves, reserveFactorMantissa));\n    }\n}\n"
      },
      "contracts/EIP20NonStandardInterface.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\n/**\n * @title EIP20NonStandardInterface\n * @dev Version of ERC20 with no return values for `transfer` and `transferFrom`\n *  See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ninterface EIP20NonStandardInterface {\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 balance The balance\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\n\n    ///\n    /// !!!!!!!!!!!!!!\n    /// !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification\n    /// !!!!!!!!!!!!!!\n    ///\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      */\n    function transfer(address dst, uint256 amount) external;\n\n    ///\n    /// !!!!!!!!!!!!!!\n    /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification\n    /// !!!!!!!!!!!!!!\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 amount The number of tokens to transfer\n      */\n    function transferFrom(address src, address dst, uint256 amount) external;\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\n      * @return success Whether or not the approval succeeded\n      */\n    function approve(address spender, uint256 amount) external returns (bool success);\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 remaining The number of tokens allowed to be spent\n      */\n    function allowance(address owner, address spender) external view returns (uint256 remaining);\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/ErrorReporter.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\ncontract ComptrollerErrorReporter {\n    enum Error {\n        NO_ERROR,\n        UNAUTHORIZED,\n        COMPTROLLER_MISMATCH,\n        INSUFFICIENT_SHORTFALL,\n        INSUFFICIENT_LIQUIDITY,\n        INVALID_CLOSE_FACTOR,\n        INVALID_COLLATERAL_FACTOR,\n        INVALID_LIQUIDATION_INCENTIVE,\n        MARKET_NOT_ENTERED, // no longer possible\n        MARKET_NOT_LISTED,\n        MARKET_ALREADY_LISTED,\n        MATH_ERROR,\n        NONZERO_BORROW_BALANCE,\n        PRICE_ERROR,\n        REJECTION,\n        SNAPSHOT_ERROR,\n        TOO_MANY_ASSETS,\n        TOO_MUCH_REPAY,\n        INVALID_MARKET_TYPE,\n        TOO_LITTLE_INTEREST_RESERVE,\n        NONZERO_INTEREST_BALANCE,\n        LIQUIDATE_SEIZE_TOO_LITTLE\n    }\n\n    enum FailureInfo {\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n        ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n        EXIT_MARKET_BALANCE_OWED,\n        EXIT_MARKET_REJECTION,\n        SET_CLOSE_FACTOR_OWNER_CHECK,\n        SET_CLOSE_FACTOR_VALIDATION,\n        SET_COLLATERAL_FACTOR_OWNER_CHECK,\n        SET_COLLATERAL_FACTOR_NO_EXISTS,\n        SET_COLLATERAL_FACTOR_VALIDATION,\n        SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\n        SET_IMPLEMENTATION_OWNER_CHECK,\n        SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\n        SET_LIQUIDATION_INCENTIVE_VALIDATION,\n        SET_MAX_ASSETS_OWNER_CHECK,\n        SET_PENDING_ADMIN_OWNER_CHECK,\n        SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\n        SET_PRICE_ORACLE_OWNER_CHECK,\n        SUPPORT_MARKET_EXISTS,\n        SUPPORT_MARKET_OWNER_CHECK,\n        SET_PAUSE_GUARDIAN_OWNER_CHECK\n    }\n\n    /**\n      * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n      * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n      **/\n    event Failure(uint error, uint info, uint detail);\n\n    error Unauthorized();\n    error InitializationFailed();\n\n    error GetAccountSnapshotFailed(uint256 errorCode);\n\n    error SeizePaused();\n    error MintPaused();\n    error BorrowPaused();\n    error CollectInterestPaused();\n    error PayInterestPaused();\n    error TransferPaused();\n\n    error InsufficientShortfall(uint errorCode, uint value);\n    error InvalidTopUpLimit();\n    error TopUpLimitExceeded();\n    error TopUpZero();\n    error SeizeFailed();\n    error TopUpFailed();\n    error LiquidateError();\n    error LiquidateSeizeTooLittle();\n    error LiquidateSeizeTooMuch();\n    error LiquidateSeizeBellowMinValue(uint minSeizedValue, uint liquidatedValueTotal);\n    error ExcessRefundFailed();\n    error BorrowCapReached();\n    error MarketAlreadyAdded();\n    error InvalidInput();\n    error OnlyAdminCanUnpause();\n    error ChangeNotAuthorized();\n\n    error MarketNotListed();\n    error SameMarket();\n    error WrongMarketType();\n    error PriceError();\n    error ComptrollerMismatch();\n    error InvalidMarket();\n\n    /**\n      * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n      */\n    function fail(Error err, FailureInfo info) internal returns (uint) {\n        emit Failure(uint(err), uint(info), 0);\n\n        return uint(err);\n    }\n\n    /**\n      * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n      */\n    function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n        emit Failure(uint(err), uint(info), opaqueError);\n\n        return uint(err);\n    }\n}\n\ncontract TokenErrorReporter {\n    uint public constant NO_ERROR = 0; // support legacy return codes\n\n    error Unauthorized();\n    error Unsupported();\n\n    error AlreadyInitialized();\n    error InitializeExchangeRateInvalid();\n    error InitializeSetComptrollerFailed(uint256 errorCode);\n    error InitializeSetInterestRateModelFailed(uint256 errorCode);\n    error InitializeMarketTypeNotSet();\n    error InitializeInvalidMarketType();\n    error EnsureNonEmptyAmountTooSmall();\n\n    error TransferComptrollerRejection(uint256 errorCode);\n    error TransferNotAllowed();\n    error TransferNotEnough();\n    error TransferTooMuch();\n    error TransferInvalidAmount();\n\n    error TransferInFailed();\n    error InsufficientBalanceAfterTransfer();\n    error TransferOutFailed();\n    error TransferFailed();\n    error NftAmountTooHigh();\n    error NftNotFound(uint256 nftId);\n\n    error MintComptrollerRejection(uint256 errorCode);\n    error MintFreshnessCheck();\n\n    error RedeemComptrollerRejection(uint256 errorCode);\n    error RedeemFreshnessCheck();\n    error RedeemTransferOutNotPossible();\n    error RedeemInvalidInputs();\n    error RedeemTokensIsZero();\n\n    error BorrowComptrollerRejection(uint256 errorCode);\n    error BorrowFreshnessCheck();\n    error BorrowCashNotAvailable();\n\n    error RepayBorrowComptrollerRejection(uint256 errorCode);\n    error RepayBorrowFreshnessCheck();\n    error RepayTooHigh();\n\n    error LiquidateComptrollerRejection(uint256 errorCode);\n    error LiquidateFreshnessCheck();\n    error LiquidateCollateralFreshnessCheck();\n    error LiquidateAccrueBorrowInterestFailed(uint256 errorCode);\n    error LiquidateAccrueCollateralInterestFailed(uint256 errorCode);\n    error LiquidateLiquidatorIsBorrower();\n    error LiquidateCloseAmountIsZero();\n    error LiquidateCloseAmountIsUintMax();\n    error LiquidateRepayBorrowFreshFailed(uint256 errorCode);\n\n    error LiquidateSeizeComptrollerRejection(uint256 errorCode);\n    error LiquidateSeizeLiquidatorIsBorrower();\n\n    error AcceptAdminPendingAdminCheck();\n\n    error SetComptrollerOwnerCheck();\n    error SetPendingAdminOwnerCheck();\n\n    error SetReserveFactorAdminCheck();\n    error SetReserveFactorFreshCheck();\n    error SetReserveFactorBoundsCheck();\n\n    error AddReservesFactorFreshCheck(uint256 actualAddAmount);\n\n    error ReduceReservesAdminCheck();\n    error ReduceReservesFreshCheck();\n    error ReduceReservesCashNotAvailable();\n    error ReduceReservesCashValidation();\n\n    error SetInterestRateModelOwnerCheck();\n    error SetInterestRateModelFreshCheck();\n\n    error SetProtocolSeizeShareAdminCheck();\n    error SetProtocolSeizeShareTooHigh();\n\n    error BorrowRateIsAbsurdlyHigh(uint borrowRateMantissa);\n\n    error InvalidComptrollerAddress(address comptrollerAddress);\n    error InvalidRateModelAddress(address interestRateModelAddress);\n\n    error Reentry();\n\n    error CannotSweepUnderlying();\n\n    error CollectInterestFailed();\n    error CollectInterestNotAllowed();\n    error PayInterestNotAllowed();\n    error InsufficientBalance();\n    error PayInterestError();\n\n    error SenderMismatch();\n    error ValueMismatch();\n\n    error PriceError();\n}\n"
      },
      "contracts/EIP20Interface.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\n/**\n * @title ERC 20 Token Standard Interface\n *  https://eips.ethereum.org/EIPS/eip-20\n */\ninterface EIP20Interface {\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 balance The balance\n     */\n    function balanceOf(address owner) external view returns (uint256 balance);\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 success Whether or not the transfer succeeded\n      */\n    function transfer(address dst, uint256 amount) external returns (bool success);\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 success Whether or not the transfer succeeded\n      */\n    function transferFrom(address src, address dst, uint256 amount) external returns (bool success);\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 success Whether or not the approval succeeded\n      */\n    function approve(address spender, uint256 amount) external returns (bool success);\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 remaining The number of tokens allowed to be spent (-1 means infinite)\n      */\n    function allowance(address owner, address spender) external view returns (uint256 remaining);\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/ExponentialNoError.sol": {
        "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.23;\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n *         Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n *         `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n    uint constant expScale = 1e18;\n    uint constant doubleScale = 1e36;\n    uint constant halfExpScale = expScale/2;\n    uint constant mantissaOne = expScale;\n\n    struct Exp {\n        uint mantissa;\n    }\n\n    struct Double {\n        uint mantissa;\n    }\n\n    /**\n     * @dev Truncates the given exp to a whole number value.\n     *      For example, truncate(Exp{mantissa: 15 * expScale}) = 15\n     */\n    function truncate(Exp memory exp) pure internal returns (uint) {\n        // Note: We are not using careful math here as we're performing a division that cannot fail\n        return exp.mantissa / expScale;\n    }\n\n    /**\n     * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n     */\n    function mul_ScalarTruncate(Exp memory a, uint scalar) pure internal returns (uint) {\n        Exp memory product = mul_(a, scalar);\n        return truncate(product);\n    }\n\n    /**\n     * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n     */\n    function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) pure internal returns (uint) {\n        Exp memory product = mul_(a, scalar);\n        return add_(truncate(product), addend);\n    }\n\n    /**\n     * @dev Checks if first Exp is less than second Exp.\n     */\n    function lessThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\n        return left.mantissa < right.mantissa;\n    }\n\n    /**\n     * @dev Checks if left Exp <= right Exp.\n     */\n    function lessThanOrEqualExp(Exp memory left, Exp memory right) pure internal returns (bool) {\n        return left.mantissa <= right.mantissa;\n    }\n\n    /**\n     * @dev Checks if left Exp > right Exp.\n     */\n    function greaterThanExp(Exp memory left, Exp memory right) pure internal returns (bool) {\n        return left.mantissa > right.mantissa;\n    }\n\n    /**\n     * @dev returns true if Exp is exactly zero\n     */\n    function isZeroExp(Exp memory value) pure internal returns (bool) {\n        return value.mantissa == 0;\n    }\n\n    function safe224(uint n, string memory errorMessage) pure internal returns (uint224) {\n        require(n < 2**224, errorMessage);\n        return uint224(n);\n    }\n\n    function safe32(uint n, string memory errorMessage) pure internal returns (uint32) {\n        require(n < 2**32, errorMessage);\n        return uint32(n);\n    }\n\n    function add_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\n        return Exp({mantissa: add_(a.mantissa, b.mantissa)});\n    }\n\n    function add_(Double memory a, Double memory b) pure internal returns (Double memory) {\n        return Double({mantissa: add_(a.mantissa, b.mantissa)});\n    }\n\n    function add_(uint a, uint b) pure internal returns (uint) {\n        return a + b;\n    }\n\n    function sub_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\n        return Exp({mantissa: sub_(a.mantissa, b.mantissa)});\n    }\n\n    function sub_(Double memory a, Double memory b) pure internal returns (Double memory) {\n        return Double({mantissa: sub_(a.mantissa, b.mantissa)});\n    }\n\n    function sub_(uint a, uint b) pure internal returns (uint) {\n        return a - b;\n    }\n\n    function mul_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\n        return Exp({mantissa: mul_(a.mantissa, b.mantissa) / expScale});\n    }\n\n    function mul_(Exp memory a, uint b) pure internal returns (Exp memory) {\n        return Exp({mantissa: mul_(a.mantissa, b)});\n    }\n\n    function mul_(uint a, Exp memory b) pure internal returns (uint) {\n        return mul_(a, b.mantissa) / expScale;\n    }\n\n    function mul_(Double memory a, Double memory b) pure internal returns (Double memory) {\n        return Double({mantissa: mul_(a.mantissa, b.mantissa) / doubleScale});\n    }\n\n    function mul_(Double memory a, uint b) pure internal returns (Double memory) {\n        return Double({mantissa: mul_(a.mantissa, b)});\n    }\n\n    function mul_(uint a, Double memory b) pure internal returns (uint) {\n        return mul_(a, b.mantissa) / doubleScale;\n    }\n\n    function mul_(uint a, uint b) pure internal returns (uint) {\n        return a * b;\n    }\n\n    function div_(Exp memory a, Exp memory b) pure internal returns (Exp memory) {\n        return Exp({mantissa: div_(mul_(a.mantissa, expScale), b.mantissa)});\n    }\n\n    function div_(Exp memory a, uint b) pure internal returns (Exp memory) {\n        return Exp({mantissa: div_(a.mantissa, b)});\n    }\n\n    function div_(uint a, Exp memory b) pure internal returns (uint) {\n        return div_(mul_(a, expScale), b.mantissa);\n    }\n\n    function div_(Double memory a, Double memory b) pure internal returns (Double memory) {\n        return Double({mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa)});\n    }\n\n    function div_(Double memory a, uint b) pure internal returns (Double memory) {\n        return Double({mantissa: div_(a.mantissa, b)});\n    }\n\n    function div_(uint a, Double memory b) pure internal returns (uint) {\n        return div_(mul_(a, doubleScale), b.mantissa);\n    }\n\n    function div_(uint a, uint b) pure internal returns (uint) {\n        return a / b;\n    }\n\n    function fraction(uint a, uint b) pure internal returns (Double memory) {\n        return Double({mantissa: div_(mul_(a, doubleScale), b)});\n    }\n}\n"
      }
    },
    "settings": {
      "evmVersion": "shanghai",
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "libraries": {
        "CErc20_PandoraDelegate.sol": {}
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}