// Vulnerability label: DC1
{{
  "language": "Solidity",
  "settings": {
    "evmVersion": "istanbul",
    "libraries": {},
    "metadata": {
      "bytecodeHash": "ipfs",
      "useLiteralContent": true
    },
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "remappings": [],
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "abi"
        ]
      }
    }
  },
  "sources": {
    "contracts/ControllerStorage.sol": {
      "content": "pragma solidity ^0.7.4;\r\n\r\nimport \"./PriceOracle.sol\";\r\n\r\ncontract UnitrollerAdminStorage {\r\n    /**\r\n    * @notice Administrator for this contract\r\n    */\r\n    address public admin;\r\n\r\n    /**\r\n    * @notice Pending administrator for this contract\r\n    */\r\n    address public pendingAdmin;\r\n\r\n    /**\r\n    * @notice Active brains of Unitroller\r\n    */\r\n    address public controllerImplementation;\r\n\r\n    /**\r\n    * @notice Pending brains of Unitroller\r\n    */\r\n    address public pendingControllerImplementation;\r\n}\r\n\r\ncontract ControllerStorage is UnitrollerAdminStorage {\r\n    /**\r\n     * @notice Oracle which gives the price of any given asset\r\n     */\r\n    PriceOracle public oracle;\r\n\r\n    /**\r\n     * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\r\n     */\r\n    uint public closeFactorMantissa;\r\n\r\n    /**\r\n     * @notice Multiplier representing the discount on collateral that a liquidator receives\r\n     */\r\n    uint public liquidationIncentiveMantissa;\r\n\r\n    /**\r\n     * @notice Max number of assets a single account can participate in (borrow or use as collateral)\r\n     */\r\n    uint public maxAssets;\r\n\r\n    /**\r\n     * @notice Per-account mapping of \"assets you are in\", capped by maxAssets\r\n     */\r\n    mapping(address => address[]) public accountAssets;\r\n\r\n    /// @notice isListed Whether or not this market is listed\r\n    /**\r\n     * @notice collateralFactorMantissa Multiplier representing the most one can borrow against their collateral in this market.\r\n     *  For instance, 0.9 to allow borrowing 90% of collateral value.\r\n     *  Must be between 0 and 1, and stored as a mantissa.\r\n     */\r\n    /// @notice accountMembership Per-market mapping of \"accounts in this asset\"\r\n    /// @notice isPied Whether or not this market receives PIE\r\n    struct Market {\r\n        bool isListed;\r\n        uint collateralFactorMantissa;\r\n        mapping(address => bool) accountMembership;\r\n        bool isPied;\r\n    }\r\n\r\n    /**\r\n     * @notice Official mapping of pTokens -> Market metadata\r\n     * @dev Used e.g. to determine if a market is supported\r\n     */\r\n    mapping(address => Market) public markets;\r\n\r\n    /**\r\n     * @notice The Pause Guardian can pause certain actions as a safety mechanism.\r\n     *  Actions which allow users to remove their own assets cannot be paused.\r\n     *  Liquidation / seizing / transfer can only be paused globally, not by market.\r\n     */\r\n    address public pauseGuardian;\r\n    bool public _mintGuardianPaused;\r\n    bool public _borrowGuardianPaused;\r\n    bool public transferGuardianPaused;\r\n    bool public seizeGuardianPaused;\r\n    mapping(address => bool) public mintGuardianPaused;\r\n    mapping(address => bool) public borrowGuardianPaused;\r\n\r\n    /// @notice index The market's last updated pieBorrowIndex or pieSupplyIndex\r\n    /// @notice block The block number the index was last updated at\r\n    struct PieMarketState {\r\n        uint224 index;\r\n        uint32 block;\r\n    }\r\n\r\n    /// @notice A list of all markets\r\n    address[] public allMarkets;\r\n\r\n    /// @notice The rate at which the flywheel distributes PIE, per block\r\n    uint public pieRate;\r\n\r\n    /// @notice Address of the PIE token\r\n    address public pieAddress;\r\n\r\n    // @notice Address of the factory\r\n    address public factory;\r\n\r\n    /// @notice The portion of pieRate that each market currently receives\r\n    mapping(address => uint) public pieSpeeds;\r\n\r\n    /// @notice The PIE market supply state for each market\r\n    mapping(address => PieMarketState) public pieSupplyState;\r\n\r\n    /// @notice The PIE market borrow state for each market\r\n    mapping(address => PieMarketState) public pieBorrowState;\r\n\r\n    /// @notice The PIE borrow index for each market for each supplier as of the last time they accrued PIE\r\n    mapping(address => mapping(address => uint)) public pieSupplierIndex;\r\n\r\n    /// @notice The PIE borrow index for each market for each borrower as of the last time they accrued PIE\r\n    mapping(address => mapping(address => uint)) public pieBorrowerIndex;\r\n\r\n    /// @notice The PIE accrued but not yet transferred to each user\r\n    mapping(address => uint) public pieAccrued;\r\n}",
      "keccak256": "0x1bfdd440933895c6990ab553fa9f5ae957da2da44008f61f73402adafe432ea7"
    },
    "contracts/ErrorReporter.sol": {
      "content": "pragma solidity ^0.7.4;\r\n\r\ncontract ControllerErrorReporter {\r\n    enum Error {\r\n        NO_ERROR,\r\n        UNAUTHORIZED,\r\n        CONTROLLER_MISMATCH,\r\n        INSUFFICIENT_SHORTFALL,\r\n        INSUFFICIENT_LIQUIDITY,\r\n        INVALID_CLOSE_FACTOR,\r\n        INVALID_COLLATERAL_FACTOR,\r\n        INVALID_LIQUIDATION_INCENTIVE,\r\n        MARKET_NOT_ENTERED, // no longer possible\r\n        MARKET_NOT_LISTED,\r\n        MARKET_ALREADY_LISTED,\r\n        MATH_ERROR,\r\n        NONZERO_BORROW_BALANCE,\r\n        PRICE_ERROR,\r\n        PRICE_UPDATE_ERROR,\r\n        REJECTION,\r\n        SNAPSHOT_ERROR,\r\n        TOO_MANY_ASSETS,\r\n        TOO_MUCH_REPAY\r\n    }\r\n\r\n    enum FailureInfo {\r\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\r\n        ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\r\n        EXIT_MARKET_BALANCE_OWED,\r\n        EXIT_MARKET_REJECTION,\r\n        SET_CLOSE_FACTOR_OWNER_CHECK,\r\n        SET_CLOSE_FACTOR_VALIDATION,\r\n        SET_COLLATERAL_FACTOR_OWNER_CHECK,\r\n        SET_COLLATERAL_FACTOR_NO_EXISTS,\r\n        SET_COLLATERAL_FACTOR_VALIDATION,\r\n        SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\r\n        SET_IMPLEMENTATION_OWNER_CHECK,\r\n        SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\r\n        SET_LIQUIDATION_INCENTIVE_VALIDATION,\r\n        SET_MAX_ASSETS_OWNER_CHECK,\r\n        SET_PAUSE_GUARDIAN_OWNER_CHECK,\r\n        SET_PENDING_ADMIN_OWNER_CHECK,\r\n        SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\r\n        SET_PRICE_ORACLE_OWNER_CHECK,\r\n        SUPPORT_MARKET_EXISTS,\r\n        SUPPORT_MARKET_OWNER_CHECK\r\n    }\r\n\r\n    /**\r\n      * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\r\n      * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\r\n      **/\r\n    event Failure(uint error, uint info, uint detail);\r\n\r\n    /**\r\n      * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\r\n      */\r\n    function fail(Error err, FailureInfo info) internal returns (uint) {\r\n        emit Failure(uint(err), uint(info), 0);\r\n\r\n        return uint(err);\r\n    }\r\n\r\n    /**\r\n      * @dev use this when reporting an opaque error from an upgradeable collaborator contract\r\n      */\r\n    function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\r\n        emit Failure(uint(err), uint(info), opaqueError);\r\n\r\n        return uint(err);\r\n    }\r\n}\r\n\r\ncontract TokenErrorReporter {\r\n    enum Error {\r\n        NO_ERROR,\r\n        UNAUTHORIZED,\r\n        BAD_INPUT,\r\n        CONTROLLER_REJECTION,\r\n        CONTROLLER_CALCULATION_ERROR,\r\n        INTEREST_RATE_MODEL_ERROR,\r\n        INVALID_ACCOUNT_PAIR,\r\n        INVALID_CLOSE_AMOUNT_REQUESTED,\r\n        INVALID_COLLATERAL_FACTOR,\r\n        MATH_ERROR,\r\n        MARKET_NOT_FRESH,\r\n        MARKET_NOT_LISTED,\r\n        TOKEN_INSUFFICIENT_ALLOWANCE,\r\n        TOKEN_INSUFFICIENT_BALANCE,\r\n        TOKEN_INSUFFICIENT_CASH,\r\n        TOKEN_TRANSFER_IN_FAILED,\r\n        TOKEN_TRANSFER_OUT_FAILED\r\n    }\r\n\r\n    /*\r\n     * Note: FailureInfo (but not Error) is kept in alphabetical order\r\n     *       This is because FailureInfo grows significantly faster, and\r\n     *       the order of Error has some meaning, while the order of FailureInfo\r\n     *       is entirely arbitrary.\r\n     */\r\n    enum FailureInfo {\r\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\r\n        ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\r\n        ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\r\n        ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\r\n        ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\r\n        ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\r\n        ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\r\n        BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\r\n        BORROW_ACCRUE_INTEREST_FAILED,\r\n        BORROW_CASH_NOT_AVAILABLE,\r\n        BORROW_FRESHNESS_CHECK,\r\n        BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\r\n        BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\r\n        BORROW_MARKET_NOT_LISTED,\r\n        BORROW_CONTROLLER_REJECTION,\r\n        LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\r\n        LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\r\n        LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\r\n        LIQUIDATE_CONTROLLER_REJECTION,\r\n        LIQUIDATE_CONTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\r\n        LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\r\n        LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\r\n        LIQUIDATE_FRESHNESS_CHECK,\r\n        LIQUIDATE_LIQUIDATOR_IS_BORROWER,\r\n        LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\r\n        LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\r\n        LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\r\n        LIQUIDATE_SEIZE_CONTROLLER_REJECTION,\r\n        LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\r\n        LIQUIDATE_SEIZE_TOO_MUCH,\r\n        MINT_ACCRUE_INTEREST_FAILED,\r\n        MINT_CONTROLLER_REJECTION,\r\n        MINT_EXCHANGE_CALCULATION_FAILED,\r\n        MINT_EXCHANGE_RATE_READ_FAILED,\r\n        MINT_FRESHNESS_CHECK,\r\n        MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\r\n        MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\r\n        MINT_TRANSFER_IN_FAILED,\r\n        MINT_TRANSFER_IN_NOT_POSSIBLE,\r\n        REDEEM_ACCRUE_INTEREST_FAILED,\r\n        REDEEM_CONTROLLER_REJECTION,\r\n        REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\r\n        REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\r\n        REDEEM_EXCHANGE_RATE_READ_FAILED,\r\n        REDEEM_FRESHNESS_CHECK,\r\n        REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\r\n        REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\r\n        REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\r\n        REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\r\n        REDUCE_RESERVES_ADMIN_CHECK,\r\n        REDUCE_RESERVES_CASH_NOT_AVAILABLE,\r\n        REDUCE_RESERVES_FRESH_CHECK,\r\n        REDUCE_RESERVES_VALIDATION,\r\n        REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\r\n        REPAY_BORROW_ACCRUE_INTEREST_FAILED,\r\n        REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\r\n        REPAY_BORROW_CONTROLLER_REJECTION,\r\n        REPAY_BORROW_FRESHNESS_CHECK,\r\n        REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\r\n        REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\r\n        REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\r\n        SET_COLLATERAL_FACTOR_OWNER_CHECK,\r\n        SET_COLLATERAL_FACTOR_VALIDATION,\r\n        SET_CONTROLLER_OWNER_CHECK,\r\n        SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\r\n        SET_INTEREST_RATE_MODEL_FRESH_CHECK,\r\n        SET_INTEREST_RATE_MODEL_OWNER_CHECK,\r\n        SET_MAX_ASSETS_OWNER_CHECK,\r\n        SET_ORACLE_MARKET_NOT_LISTED,\r\n        SET_PENDING_ADMIN_OWNER_CHECK,\r\n        SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\r\n        SET_RESERVE_FACTOR_ADMIN_CHECK,\r\n        SET_RESERVE_FACTOR_FRESH_CHECK,\r\n        SET_RESERVE_FACTOR_BOUNDS_CHECK,\r\n        TRANSFER_CONTROLLER_REJECTION,\r\n        TRANSFER_NOT_ALLOWED,\r\n        TRANSFER_NOT_ENOUGH,\r\n        TRANSFER_TOO_MUCH,\r\n        ADD_RESERVES_ACCRUE_INTEREST_FAILED,\r\n        ADD_RESERVES_FRESH_CHECK,\r\n        ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\r\n        SET_NEW_IMPLEMENTATION\r\n    }\r\n\r\n    /**\r\n      * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\r\n      * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\r\n      **/\r\n    event Failure(uint error, uint info, uint detail);\r\n\r\n    /**\r\n      * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\r\n      */\r\n    function fail(Error err, FailureInfo info) internal returns (uint) {\r\n        emit Failure(uint(err), uint(info), 0);\r\n\r\n        return uint(err);\r\n    }\r\n\r\n    /**\r\n      * @dev use this when reporting an opaque error from an upgradeable collaborator contract\r\n      */\r\n    function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\r\n        emit Failure(uint(err), uint(info), opaqueError);\r\n\r\n        return uint(err);\r\n    }\r\n}\r\n\r\ncontract OracleErrorReporter {\r\n    enum Error {\r\n        NO_ERROR,\r\n        UNAUTHORIZED,\r\n        UPDATE_PRICE\r\n    }\r\n\r\n    enum FailureInfo {\r\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\r\n        NO_RESERVES,\r\n        PERIOD_NOT_ELAPSED,\r\n        SET_NEW_ADDRESSES,\r\n        SET_NEW_IMPLEMENTATION,\r\n        SET_PENDING_ADMIN_OWNER_CHECK\r\n    }\r\n\r\n    /**\r\n      * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\r\n      * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\r\n      **/\r\n    event Failure(uint error, uint info, uint detail);\r\n\r\n    /**\r\n      * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\r\n      */\r\n    function fail(Error err, FailureInfo info) internal returns (uint) {\r\n        emit Failure(uint(err), uint(info), 0);\r\n\r\n        return uint(err);\r\n    }\r\n}\r\n\r\ncontract FactoryErrorReporter {\r\n    enum Error {\r\n        NO_ERROR,\r\n        INVALID_POOL,\r\n        MARKET_NOT_LISTED,\r\n        UNAUTHORIZED\r\n    }\r\n\r\n    //TODO: Add more cases\r\n    enum FailureInfo {\r\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\r\n        CREATE_PETH_POOL,\r\n        CREATE_PPIE_POOL,\r\n        DEFICIENCY_ETH_LIQUIDITY_IN_POOL,\r\n        PAIR_IS_NOT_EXIST,\r\n        SET_MIN_LIQUIDITY_OWNER_CHECK,\r\n        SET_NEW_CONTROLLER,\r\n        SET_NEW_EXCHANGE_RATE,\r\n        SET_NEW_IMPLEMENTATION,\r\n        SET_NEW_INTEREST_RATE_MODEL,\r\n        SET_NEW_ORACLE,\r\n        SET_NEW_RESERVE_FACTOR,\r\n        SET_PENDING_ADMIN_OWNER_CHECK,\r\n        SUPPORT_MARKET_BAD_RESULT\r\n    }\r\n\r\n    /**\r\n      * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\r\n      * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\r\n      **/\r\n    event Failure(uint error, uint info, uint detail);\r\n\r\n    /**\r\n      * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\r\n      */\r\n    function fail(Error err, FailureInfo info) internal returns (uint) {\r\n        emit Failure(uint(err), uint(info), 0);\r\n\r\n        return uint(err);\r\n    }\r\n}\r\n\r\ncontract RegistryErrorReporter {\r\n    enum Error {\r\n        NO_ERROR,\r\n        UNAUTHORIZED\r\n    }\r\n\r\n    //TODO: Add more cases\r\n    enum FailureInfo {\r\n        ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\r\n        SET_NEW_IMPLEMENTATION,\r\n        SET_PENDING_ADMIN_OWNER_CHECK,\r\n        SET_NEW_FACTORY\r\n    }\r\n\r\n    /**\r\n      * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\r\n      * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\r\n      **/\r\n    event Failure(uint error, uint info, uint detail);\r\n\r\n    /**\r\n      * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\r\n      */\r\n    function fail(Error err, FailureInfo info) internal returns (uint) {\r\n        emit Failure(uint(err), uint(info), 0);\r\n\r\n        return uint(err);\r\n    }\r\n}",
      "keccak256": "0xe1bcb3a482a468266ee892e6df9f563fc2513931fa929b3a6188353ffc491aa3"
    },
    "contracts/PriceOracle.sol": {
      "content": "pragma solidity ^0.7.4;\r\n\r\nabstract contract PriceOracle {\r\n    /// @notice Indicator that this is a PriceOracle contract (for inspection)\r\n    bool public constant isPriceOracle = true;\r\n\r\n    event PriceUpdated(address asset, uint price);\r\n\r\n    /**\r\n      * @notice Get the underlying price of a pToken asset\r\n      * @param pToken The pToken to get the underlying price of\r\n      * @return The underlying asset price mantissa (scaled by 1e18).\r\n      *  Zero means the price is unavailable.\r\n      */\r\n    function getUnderlyingPrice(address pToken) external view virtual returns (uint);\r\n\r\n    function updateUnderlyingPrice(address pToken) external virtual returns (uint);\r\n}",
      "keccak256": "0x9819a9a63bfc68ed841974b5da2f0ee27ae4baae87670fb99188a33186f35404"
    },
    "contracts/Unitroller.sol": {
      "content": "pragma solidity ^0.7.4;\r\n\r\nimport \"./ErrorReporter.sol\";\r\nimport \"./ControllerStorage.sol\";\r\n/**\r\n * @title ControllerCore\r\n * @dev Storage for the controller is at this address, while execution is delegated to the `controllerImplementation`.\r\n * PTokens should reference this contract as their controller.\r\n */\r\ncontract Unitroller is UnitrollerAdminStorage, ControllerErrorReporter {\r\n\r\n    /**\r\n      * @notice Emitted when pendingControllerImplementation is changed\r\n      */\r\n    event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\r\n\r\n    /**\r\n      * @notice Emitted when pendingControllerImplementation is accepted, which means controller implementation is updated\r\n      */\r\n    event NewImplementation(address oldImplementation, address newImplementation);\r\n\r\n    /**\r\n      * @notice Emitted when pendingAdmin is changed\r\n      */\r\n    event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\r\n\r\n    /**\r\n      * @notice Emitted when pendingAdmin is accepted, which means admin is updated\r\n      */\r\n    event NewAdmin(address oldAdmin, address newAdmin);\r\n\r\n    constructor() {\r\n        // Set admin to caller\r\n        admin = msg.sender;\r\n    }\r\n\r\n    /*** Admin Functions ***/\r\n    function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\r\n\r\n        if (msg.sender != admin) {\r\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\r\n        }\r\n\r\n        address oldPendingImplementation = pendingControllerImplementation;\r\n\r\n        pendingControllerImplementation = newPendingImplementation;\r\n\r\n        emit NewPendingImplementation(oldPendingImplementation, pendingControllerImplementation);\r\n\r\n        return uint(Error.NO_ERROR);\r\n    }\r\n\r\n    /**\r\n    * @notice Accepts new implementation of controller. msg.sender must be pendingImplementation\r\n    * @dev Admin function for new implementation to accept it's role as implementation\r\n    * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\r\n    */\r\n    function _acceptImplementation() public returns (uint) {\r\n        // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\r\n        if (msg.sender != pendingControllerImplementation || pendingControllerImplementation == address(0)) {\r\n            return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\r\n        }\r\n\r\n        // Save current values for inclusion in log\r\n        address oldImplementation = controllerImplementation;\r\n        address oldPendingImplementation = pendingControllerImplementation;\r\n\r\n        controllerImplementation = pendingControllerImplementation;\r\n\r\n        pendingControllerImplementation = address(0);\r\n\r\n        emit NewImplementation(oldImplementation, controllerImplementation);\r\n        emit NewPendingImplementation(oldPendingImplementation, pendingControllerImplementation);\r\n\r\n        return uint(Error.NO_ERROR);\r\n    }\r\n\r\n\r\n    /**\r\n      * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\r\n      * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\r\n      * @param newPendingAdmin New pending admin.\r\n      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\r\n      */\r\n    function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\r\n        // Check caller = admin\r\n        if (msg.sender != admin) {\r\n            return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\r\n        }\r\n\r\n        // Save current value, if any, for inclusion in log\r\n        address oldPendingAdmin = pendingAdmin;\r\n\r\n        // Store pendingAdmin with value newPendingAdmin\r\n        pendingAdmin = newPendingAdmin;\r\n\r\n        // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\r\n        emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\r\n\r\n        return uint(Error.NO_ERROR);\r\n    }\r\n\r\n    /**\r\n      * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\r\n      * @dev Admin function for pending admin to accept role and update admin\r\n      * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\r\n      */\r\n    function _acceptAdmin() public returns (uint) {\r\n        // Check caller is pendingAdmin and pendingAdmin ≠ address(0)\r\n        if (msg.sender != pendingAdmin || msg.sender == address(0)) {\r\n            return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\r\n        }\r\n\r\n        // Save current values for inclusion in log\r\n        address oldAdmin = admin;\r\n        address oldPendingAdmin = pendingAdmin;\r\n\r\n        // Store admin with value pendingAdmin\r\n        admin = pendingAdmin;\r\n\r\n        // Clear the pending value\r\n        pendingAdmin = address(0);\r\n\r\n        emit NewAdmin(oldAdmin, admin);\r\n        emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\r\n\r\n        return uint(Error.NO_ERROR);\r\n    }\r\n\r\n    /**\r\n     * @dev Delegates execution to an implementation contract.\r\n     * It returns to the external caller whatever the implementation returns\r\n     * or forwards reverts.\r\n     */\r\n    fallback() payable external {\r\n        // delegate all other functions to current implementation\r\n        (bool success, ) = controllerImplementation.delegatecall(msg.data);\r\n\r\n        assembly {\r\n        let free_mem_ptr := mload(0x40)\r\n            returndatacopy(free_mem_ptr, 0, returndatasize())\r\n\r\n            switch success\r\n            case 0 { revert(free_mem_ptr, returndatasize()) }\r\n            default { return(free_mem_ptr, returndatasize()) }\r\n        }\r\n    }\r\n\r\n    receive() payable external {\r\n        require(msg.value == 0, \"unitroller should not get ether\");\r\n    }\r\n}",
      "keccak256": "0x94e274a94d0ed9885b4ce0c37ce8a059426b94d471f77b7a8d2ed9b18d6393d6"
    }
  }
}}