creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "lib/blueberry-core/contracts/money-market/PriceOracle/v1PriceOracle.sol": {
        "content": "pragma solidity 0.5.16;\n\ncontract ErrorReporter {\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(uint256 error, uint256 info, uint256 detail);\n\n    enum Error {\n        NO_ERROR,\n        OPAQUE_ERROR, // To be used when reporting errors from upgradeable contracts; the opaque code should be given as `detail` in the `Failure` event\n        UNAUTHORIZED,\n        INTEGER_OVERFLOW,\n        INTEGER_UNDERFLOW,\n        DIVISION_BY_ZERO,\n        BAD_INPUT,\n        TOKEN_INSUFFICIENT_ALLOWANCE,\n        TOKEN_INSUFFICIENT_BALANCE,\n        TOKEN_TRANSFER_FAILED,\n        MARKET_NOT_SUPPORTED,\n        SUPPLY_RATE_CALCULATION_FAILED,\n        BORROW_RATE_CALCULATION_FAILED,\n        TOKEN_INSUFFICIENT_CASH,\n        TOKEN_TRANSFER_OUT_FAILED,\n        INSUFFICIENT_LIQUIDITY,\n        INSUFFICIENT_BALANCE,\n        INVALID_COLLATERAL_RATIO,\n        MISSING_ASSET_PRICE,\n        EQUITY_INSUFFICIENT_BALANCE,\n        INVALID_CLOSE_AMOUNT_REQUESTED,\n        ASSET_NOT_PRICED,\n        INVALID_LIQUIDATION_DISCOUNT,\n        INVALID_COMBINED_RISK_PARAMETERS\n    }\n\n    /*\n     * Note: FailureInfo (but not Error) is kept in alphabetical order\n     *       This is because FailureInfo grows significantly faster, and\n     *       the order of Error has some meaning, while the order of FailureInfo\n     *       is entirely arbitrary.\n     */\n    enum FailureInfo {\n        BORROW_ACCOUNT_LIQUIDITY_CALCULATION_FAILED,\n        BORROW_ACCOUNT_SHORTFALL_PRESENT,\n        BORROW_AMOUNT_LIQUIDITY_SHORTFALL,\n        BORROW_AMOUNT_VALUE_CALCULATION_FAILED,\n        BORROW_MARKET_NOT_SUPPORTED,\n        BORROW_NEW_BORROW_INDEX_CALCULATION_FAILED,\n        BORROW_NEW_BORROW_RATE_CALCULATION_FAILED,\n        BORROW_NEW_SUPPLY_INDEX_CALCULATION_FAILED,\n        BORROW_NEW_SUPPLY_RATE_CALCULATION_FAILED,\n        BORROW_NEW_TOTAL_BORROW_CALCULATION_FAILED,\n        BORROW_NEW_TOTAL_CASH_CALCULATION_FAILED,\n        BORROW_ORIGINATION_FEE_CALCULATION_FAILED,\n        BORROW_TRANSFER_OUT_FAILED,\n        EQUITY_WITHDRAWAL_AMOUNT_VALIDATION,\n        EQUITY_WITHDRAWAL_CALCULATE_EQUITY,\n        EQUITY_WITHDRAWAL_MODEL_OWNER_CHECK,\n        EQUITY_WITHDRAWAL_TRANSFER_OUT_FAILED,\n        LIQUIDATE_ACCUMULATED_BORROW_BALANCE_CALCULATION_FAILED,\n        LIQUIDATE_ACCUMULATED_SUPPLY_BALANCE_CALCULATION_FAILED_BORROWER_COLLATERAL_ASSET,\n        LIQUIDATE_ACCUMULATED_SUPPLY_BALANCE_CALCULATION_FAILED_LIQUIDATOR_COLLATERAL_ASSET,\n        LIQUIDATE_AMOUNT_SEIZE_CALCULATION_FAILED,\n        LIQUIDATE_BORROW_DENOMINATED_COLLATERAL_CALCULATION_FAILED,\n        LIQUIDATE_CLOSE_AMOUNT_TOO_HIGH,\n        LIQUIDATE_DISCOUNTED_REPAY_TO_EVEN_AMOUNT_CALCULATION_FAILED,\n        LIQUIDATE_NEW_BORROW_INDEX_CALCULATION_FAILED_BORROWED_ASSET,\n        LIQUIDATE_NEW_BORROW_INDEX_CALCULATION_FAILED_COLLATERAL_ASSET,\n        LIQUIDATE_NEW_BORROW_RATE_CALCULATION_FAILED_BORROWED_ASSET,\n        LIQUIDATE_NEW_SUPPLY_INDEX_CALCULATION_FAILED_BORROWED_ASSET,\n        LIQUIDATE_NEW_SUPPLY_INDEX_CALCULATION_FAILED_COLLATERAL_ASSET,\n        LIQUIDATE_NEW_SUPPLY_RATE_CALCULATION_FAILED_BORROWED_ASSET,\n        LIQUIDATE_NEW_TOTAL_BORROW_CALCULATION_FAILED_BORROWED_ASSET,\n        LIQUIDATE_NEW_TOTAL_CASH_CALCULATION_FAILED_BORROWED_ASSET,\n        LIQUIDATE_NEW_TOTAL_SUPPLY_BALANCE_CALCULATION_FAILED_BORROWER_COLLATERAL_ASSET,\n        LIQUIDATE_NEW_TOTAL_SUPPLY_BALANCE_CALCULATION_FAILED_LIQUIDATOR_COLLATERAL_ASSET,\n        LIQUIDATE_TRANSFER_IN_FAILED,\n        LIQUIDATE_TRANSFER_IN_NOT_POSSIBLE,\n        REPAY_BORROW_NEW_BORROW_INDEX_CALCULATION_FAILED,\n        REPAY_BORROW_NEW_BORROW_RATE_CALCULATION_FAILED,\n        REPAY_BORROW_NEW_SUPPLY_INDEX_CALCULATION_FAILED,\n        REPAY_BORROW_NEW_SUPPLY_RATE_CALCULATION_FAILED,\n        REPAY_BORROW_NEW_TOTAL_BORROW_CALCULATION_FAILED,\n        REPAY_BORROW_NEW_TOTAL_CASH_CALCULATION_FAILED,\n        REPAY_BORROW_TRANSFER_IN_FAILED,\n        REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\n        SET_ADMIN_OWNER_CHECK,\n        SET_ASSET_PRICE_CHECK_ORACLE,\n        SET_MARKET_INTEREST_RATE_MODEL_OWNER_CHECK,\n        SET_ORACLE_OWNER_CHECK,\n        SET_ORIGINATION_FEE_OWNER_CHECK,\n        SET_RISK_PARAMETERS_OWNER_CHECK,\n        SET_RISK_PARAMETERS_VALIDATION,\n        SUPPLY_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n        SUPPLY_MARKET_NOT_SUPPORTED,\n        SUPPLY_NEW_BORROW_INDEX_CALCULATION_FAILED,\n        SUPPLY_NEW_BORROW_RATE_CALCULATION_FAILED,\n        SUPPLY_NEW_SUPPLY_INDEX_CALCULATION_FAILED,\n        SUPPLY_NEW_SUPPLY_RATE_CALCULATION_FAILED,\n        SUPPLY_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n        SUPPLY_NEW_TOTAL_CASH_CALCULATION_FAILED,\n        SUPPLY_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n        SUPPLY_TRANSFER_IN_FAILED,\n        SUPPLY_TRANSFER_IN_NOT_POSSIBLE,\n        SUPPORT_MARKET_OWNER_CHECK,\n        SUPPORT_MARKET_PRICE_CHECK,\n        SUSPEND_MARKET_OWNER_CHECK,\n        WITHDRAW_ACCOUNT_LIQUIDITY_CALCULATION_FAILED,\n        WITHDRAW_ACCOUNT_SHORTFALL_PRESENT,\n        WITHDRAW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n        WITHDRAW_AMOUNT_LIQUIDITY_SHORTFALL,\n        WITHDRAW_AMOUNT_VALUE_CALCULATION_FAILED,\n        WITHDRAW_CAPACITY_CALCULATION_FAILED,\n        WITHDRAW_NEW_BORROW_INDEX_CALCULATION_FAILED,\n        WITHDRAW_NEW_BORROW_RATE_CALCULATION_FAILED,\n        WITHDRAW_NEW_SUPPLY_INDEX_CALCULATION_FAILED,\n        WITHDRAW_NEW_SUPPLY_RATE_CALCULATION_FAILED,\n        WITHDRAW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n        WITHDRAW_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n        WITHDRAW_TRANSFER_OUT_FAILED,\n        WITHDRAW_TRANSFER_OUT_NOT_POSSIBLE\n    }\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 (uint256) {\n        emit Failure(uint256(err), uint256(info), 0);\n\n        return uint256(err);\n    }\n\n    /**\n     * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n     */\n    function failOpaque(FailureInfo info, uint256 opaqueError)\n        internal\n        returns (uint256)\n    {\n        emit Failure(uint256(Error.OPAQUE_ERROR), uint256(info), opaqueError);\n\n        return uint256(Error.OPAQUE_ERROR);\n    }\n}\n\ncontract CarefulMath is ErrorReporter {\n    /**\n     * @dev Multiplies two numbers, returns an error on overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (Error, uint256) {\n        if (a == 0) {\n            return (Error.NO_ERROR, 0);\n        }\n\n        uint256 c = a * b;\n\n        if (c / a != b) {\n            return (Error.INTEGER_OVERFLOW, 0);\n        } else {\n            return (Error.NO_ERROR, c);\n        }\n    }\n\n    /**\n     * @dev Integer division of two numbers, truncating the quotient.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (Error, uint256) {\n        if (b == 0) {\n            return (Error.DIVISION_BY_ZERO, 0);\n        }\n\n        return (Error.NO_ERROR, a / b);\n    }\n\n    /**\n     * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (Error, uint256) {\n        if (b <= a) {\n            return (Error.NO_ERROR, a - b);\n        } else {\n            return (Error.INTEGER_UNDERFLOW, 0);\n        }\n    }\n\n    /**\n     * @dev Adds two numbers, returns an error on overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (Error, uint256) {\n        uint256 c = a + b;\n\n        if (c >= a) {\n            return (Error.NO_ERROR, c);\n        } else {\n            return (Error.INTEGER_OVERFLOW, 0);\n        }\n    }\n\n    /**\n     * @dev add a and b and then subtract c\n     */\n    function addThenSub(\n        uint256 a,\n        uint256 b,\n        uint256 c\n    ) internal pure returns (Error, uint256) {\n        (Error err0, uint256 sum) = add(a, b);\n\n        if (err0 != Error.NO_ERROR) {\n            return (err0, 0);\n        }\n\n        return sub(sum, c);\n    }\n}\n\ncontract Exponential is ErrorReporter, CarefulMath {\n    // TODO: We may wish to put the result of 10**18 here instead of the expression.\n    // Per https://solidity.readthedocs.io/en/latest/contracts.html#constant-state-variables\n    // the optimizer MAY replace the expression 10**18 with its calculated value.\n    uint256 constant expScale = 10**18;\n\n    // See TODO on expScale\n    uint256 constant halfExpScale = expScale / 2;\n\n    struct Exp {\n        uint256 mantissa;\n    }\n\n    uint256 constant mantissaOne = 10**18;\n    uint256 constant mantissaOneTenth = 10**17;\n\n    /**\n     * @dev Creates an exponential from numerator and denominator values.\n     *      Note: Returns an error if (`num` * 10e18) > MAX_INT,\n     *            or if `denom` is zero.\n     */\n    function getExp(uint256 num, uint256 denom)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        (Error err0, uint256 scaledNumerator) = mul(num, expScale);\n        if (err0 != Error.NO_ERROR) {\n            return (err0, Exp({mantissa: 0}));\n        }\n\n        (Error err1, uint256 rational) = div(scaledNumerator, denom);\n        if (err1 != Error.NO_ERROR) {\n            return (err1, Exp({mantissa: 0}));\n        }\n\n        return (Error.NO_ERROR, Exp({mantissa: rational}));\n    }\n\n    /**\n     * @dev Adds two exponentials, returning a new exponential.\n     */\n    function addExp(Exp memory a, Exp memory b)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        (Error error, uint256 result) = add(a.mantissa, b.mantissa);\n\n        return (error, Exp({mantissa: result}));\n    }\n\n    /**\n     * @dev Subtracts two exponentials, returning a new exponential.\n     */\n    function subExp(Exp memory a, Exp memory b)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        (Error error, uint256 result) = sub(a.mantissa, b.mantissa);\n\n        return (error, Exp({mantissa: result}));\n    }\n\n    /**\n     * @dev Multiply an Exp by a scalar, returning a new Exp.\n     */\n    function mulScalar(Exp memory a, uint256 scalar)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        (Error err0, uint256 scaledMantissa) = mul(a.mantissa, scalar);\n        if (err0 != Error.NO_ERROR) {\n            return (err0, Exp({mantissa: 0}));\n        }\n\n        return (Error.NO_ERROR, Exp({mantissa: scaledMantissa}));\n    }\n\n    /**\n     * @dev Divide an Exp by a scalar, returning a new Exp.\n     */\n    function divScalar(Exp memory a, uint256 scalar)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        (Error err0, uint256 descaledMantissa) = div(a.mantissa, scalar);\n        if (err0 != Error.NO_ERROR) {\n            return (err0, Exp({mantissa: 0}));\n        }\n\n        return (Error.NO_ERROR, Exp({mantissa: descaledMantissa}));\n    }\n\n    /**\n     * @dev Divide a scalar by an Exp, returning a new Exp.\n     */\n    function divScalarByExp(uint256 scalar, Exp memory divisor)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        /*\n            We are doing this as:\n            getExp(mul(expScale, scalar), divisor.mantissa)\n\n            How it works:\n            Exp = a / b;\n            Scalar = s;\n            `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\n        */\n        (Error err0, uint256 numerator) = mul(expScale, scalar);\n        if (err0 != Error.NO_ERROR) {\n            return (err0, Exp({mantissa: 0}));\n        }\n        return getExp(numerator, divisor.mantissa);\n    }\n\n    /**\n     * @dev Multiplies two exponentials, returning a new exponential.\n     */\n    function mulExp(Exp memory a, Exp memory b)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        (Error err0, uint256 doubleScaledProduct) = mul(a.mantissa, b.mantissa);\n        if (err0 != Error.NO_ERROR) {\n            return (err0, Exp({mantissa: 0}));\n        }\n\n        // We add half the scale before dividing so that we get rounding instead of truncation.\n        //  See \"Listing 6\" and text above it at https://accu.org/index.php/journals/1717\n        // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\n        (Error err1, uint256 doubleScaledProductWithHalfScale) = add(\n            halfExpScale,\n            doubleScaledProduct\n        );\n        if (err1 != Error.NO_ERROR) {\n            return (err1, Exp({mantissa: 0}));\n        }\n\n        (Error err2, uint256 product) = div(\n            doubleScaledProductWithHalfScale,\n            expScale\n        );\n        // The only error `div` can return is Error.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\n        assert(err2 == Error.NO_ERROR);\n\n        return (Error.NO_ERROR, Exp({mantissa: product}));\n    }\n\n    /**\n     * @dev Divides two exponentials, returning a new exponential.\n     *     (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\n     *  which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\n     */\n    function divExp(Exp memory a, Exp memory b)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        return getExp(a.mantissa, b.mantissa);\n    }\n\n    /**\n     * @dev Truncates the given exp to a whole number value.\n     *      For example, truncate(Exp{mantissa: 15 * (10**18)}) = 15\n     */\n    function truncate(Exp memory exp) internal pure returns (uint256) {\n        // Note: We are not using careful math here as we're performing a division that cannot fail\n        return exp.mantissa / 10**18;\n    }\n\n    /**\n     * @dev Checks if first Exp is less than second Exp.\n     */\n    function lessThanExp(Exp memory left, Exp memory right)\n        internal\n        pure\n        returns (bool)\n    {\n        return left.mantissa < right.mantissa; //TODO: Add some simple tests and this in another PR yo.\n    }\n\n    /**\n     * @dev Checks if left Exp <= right Exp.\n     */\n    function lessThanOrEqualExp(Exp memory left, Exp memory right)\n        internal\n        pure\n        returns (bool)\n    {\n        return left.mantissa <= right.mantissa;\n    }\n\n    /**\n     * @dev Checks if first Exp is greater than second Exp.\n     */\n    function greaterThanExp(Exp memory left, Exp memory right)\n        internal\n        pure\n        returns (bool)\n    {\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) internal pure returns (bool) {\n        return value.mantissa == 0;\n    }\n}\n\ncontract PriceOracle is Exponential {\n    /**\n     * @dev flag for whether or not contract is paused\n     *\n     */\n    bool public paused;\n\n    uint256 public constant numBlocksPerPeriod = 297; // approximately 1 hour: 60 seconds/minute * 60 minutes/hour * 1 block/12.1212 seconds\n\n    uint256 public constant maxSwingMantissa = (10**17); // 0.1\n\n    /**\n     * @dev Mapping of asset addresses and their corresponding price in terms of Eth-Wei\n     *      which is simply equal to AssetWeiPrice * 10e18. For instance, if OMG token was\n     *      worth 5x Eth then the price for OMG would be 5*10e18 or Exp({mantissa: 5000000000000000000}).\n     * map: assetAddress -> Exp\n     */\n    mapping(address => Exp) public _assetPrices;\n\n    constructor(address _poster) public {\n        anchorAdmin = msg.sender;\n        poster = _poster;\n        maxSwing = Exp({mantissa: maxSwingMantissa});\n    }\n\n    /**\n     * @notice Do not pay into PriceOracle\n     */\n    function() external payable {\n        revert();\n    }\n\n    enum OracleError {\n        NO_ERROR,\n        UNAUTHORIZED,\n        FAILED_TO_SET_PRICE\n    }\n\n    enum OracleFailureInfo {\n        ACCEPT_ANCHOR_ADMIN_PENDING_ANCHOR_ADMIN_CHECK,\n        SET_PAUSED_OWNER_CHECK,\n        SET_PENDING_ANCHOR_ADMIN_OWNER_CHECK,\n        SET_PENDING_ANCHOR_PERMISSION_CHECK,\n        SET_PRICE_CALCULATE_SWING,\n        SET_PRICE_CAP_TO_MAX,\n        SET_PRICE_MAX_SWING_CHECK,\n        SET_PRICE_NO_ANCHOR_PRICE_OR_INITIAL_PRICE_ZERO,\n        SET_PRICE_PERMISSION_CHECK,\n        SET_PRICE_ZERO_PRICE,\n        SET_PRICES_PARAM_VALIDATION\n    }\n\n    /**\n     * @dev `msgSender` is msg.sender; `error` corresponds to enum OracleError; `info` corresponds to enum OracleFailureInfo, and `detail` is an arbitrary\n     * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n     **/\n    event OracleFailure(\n        address msgSender,\n        address asset,\n        uint256 error,\n        uint256 info,\n        uint256 detail\n    );\n\n    /**\n     * @dev use this when reporting a known error from the price oracle or a non-upgradeable collaborator\n     *      Using Oracle in name because we already inherit a `fail` function from ErrorReporter.sol via Exponential.sol\n     */\n    function failOracle(\n        address asset,\n        OracleError err,\n        OracleFailureInfo info\n    ) internal returns (uint256) {\n        emit OracleFailure(msg.sender, asset, uint256(err), uint256(info), 0);\n\n        return uint256(err);\n    }\n\n    /**\n     * @dev Use this when reporting an error from the money market. Give the money market result as `details`\n     */\n    function failOracleWithDetails(\n        address asset,\n        OracleError err,\n        OracleFailureInfo info,\n        uint256 details\n    ) internal returns (uint256) {\n        emit OracleFailure(\n            msg.sender,\n            asset,\n            uint256(err),\n            uint256(info),\n            details\n        );\n\n        return uint256(err);\n    }\n\n    /**\n     * @dev An administrator who can set the pending anchor value for assets.\n     *      Set in the constructor.\n     */\n    address public anchorAdmin;\n\n    /**\n     * @dev pending anchor administrator for this contract.\n     */\n    address public pendingAnchorAdmin;\n\n    /**\n     * @dev Address of the price poster.\n     *      Set in the constructor.\n     */\n    address public poster;\n\n    /**\n     * @dev maxSwing the maximum allowed percentage difference between a new price and the anchor's price\n     *      Set only in the constructor\n     */\n    Exp public maxSwing;\n\n    struct Anchor {\n        // floor(block.number / numBlocksPerPeriod) + 1\n        uint256 period;\n        // Price in ETH, scaled by 10**18\n        uint256 priceMantissa;\n    }\n\n    /**\n     * @dev anchors by asset\n     */\n    mapping(address => Anchor) public anchors;\n\n    /**\n     * @dev pending anchor prices by asset\n     */\n    mapping(address => uint256) public pendingAnchors;\n\n    /**\n     * @dev emitted when a pending anchor is set\n     * @param asset Asset for which to set a pending anchor\n     * @param oldScaledPrice if an unused pending anchor was present, its value; otherwise 0.\n     * @param newScaledPrice the new scaled pending anchor price\n     */\n    event NewPendingAnchor(\n        address anchorAdmin,\n        address asset,\n        uint256 oldScaledPrice,\n        uint256 newScaledPrice\n    );\n\n    /**\n     * @notice provides ability to override the anchor price for an asset\n     * @dev Admin function to set the anchor price for an asset\n     * @param asset Asset for which to override the anchor price\n     * @param newScaledPrice New anchor price\n     * @return uint 0=success, otherwise a failure (see enum OracleError for details)\n     */\n    function _setPendingAnchor(address asset, uint256 newScaledPrice)\n        public\n        returns (uint256)\n    {\n        // Check caller = anchorAdmin. Note: Deliberately not allowing admin. They can just change anchorAdmin if desired.\n        if (msg.sender != anchorAdmin) {\n            return\n                failOracle(\n                    asset,\n                    OracleError.UNAUTHORIZED,\n                    OracleFailureInfo.SET_PENDING_ANCHOR_PERMISSION_CHECK\n                );\n        }\n\n        uint256 oldScaledPrice = pendingAnchors[asset];\n        pendingAnchors[asset] = newScaledPrice;\n\n        emit NewPendingAnchor(\n            msg.sender,\n            asset,\n            oldScaledPrice,\n            newScaledPrice\n        );\n\n        return uint256(OracleError.NO_ERROR);\n    }\n\n    /**\n     * @dev emitted for all price changes\n     */\n    event PricePosted(\n        address asset,\n        uint256 previousPriceMantissa,\n        uint256 requestedPriceMantissa,\n        uint256 newPriceMantissa\n    );\n\n    /**\n     * @dev emitted if this contract successfully posts a capped-to-max price to the money market\n     */\n    event CappedPricePosted(\n        address asset,\n        uint256 requestedPriceMantissa,\n        uint256 anchorPriceMantissa,\n        uint256 cappedPriceMantissa\n    );\n\n    /**\n     * @dev emitted when admin either pauses or resumes the contract; newState is the resulting state\n     */\n    event SetPaused(bool newState);\n\n    /**\n     * @dev emitted when pendingAnchorAdmin is changed\n     */\n    event NewPendingAnchorAdmin(\n        address oldPendingAnchorAdmin,\n        address newPendingAnchorAdmin\n    );\n\n    /**\n     * @dev emitted when pendingAnchorAdmin is accepted, which means anchor admin is updated\n     */\n    event NewAnchorAdmin(address oldAnchorAdmin, address newAnchorAdmin);\n\n    /**\n     * @notice set `paused` to the specified state\n     * @dev Admin function to pause or resume the market\n     * @param requestedState value to assign to `paused`\n     * @return uint 0=success, otherwise a failure\n     */\n    function _setPaused(bool requestedState) public returns (uint256) {\n        // Check caller = anchorAdmin\n        if (msg.sender != anchorAdmin) {\n            return\n                failOracle(\n                    address(0),\n                    OracleError.UNAUTHORIZED,\n                    OracleFailureInfo.SET_PAUSED_OWNER_CHECK\n                );\n        }\n\n        paused = requestedState;\n        emit SetPaused(requestedState);\n\n        return uint256(Error.NO_ERROR);\n    }\n\n    /**\n     * @notice Begins transfer of anchor admin rights. The newPendingAnchorAdmin must call `_acceptAnchorAdmin` to finalize the transfer.\n     * @dev Admin function to begin change of anchor admin. The newPendingAnchorAdmin must call `_acceptAnchorAdmin` to finalize the transfer.\n     * @param newPendingAnchorAdmin New pending anchor admin.\n     * @return uint 0=success, otherwise a failure\n     *\n     * TODO: Should we add a second arg to verify, like a checksum of `newAnchorAdmin` address?\n     */\n    function _setPendingAnchorAdmin(address newPendingAnchorAdmin)\n        public\n        returns (uint256)\n    {\n        // Check caller = anchorAdmin\n        if (msg.sender != anchorAdmin) {\n            return\n                failOracle(\n                    address(0),\n                    OracleError.UNAUTHORIZED,\n                    OracleFailureInfo.SET_PENDING_ANCHOR_ADMIN_OWNER_CHECK\n                );\n        }\n\n        // save current value, if any, for inclusion in log\n        address oldPendingAnchorAdmin = pendingAnchorAdmin;\n        // Store pendingAdmin = newPendingAdmin\n        pendingAnchorAdmin = newPendingAnchorAdmin;\n\n        emit NewPendingAnchorAdmin(\n            oldPendingAnchorAdmin,\n            newPendingAnchorAdmin\n        );\n\n        return uint256(Error.NO_ERROR);\n    }\n\n    /**\n     * @notice Accepts transfer of anchor admin rights. msg.sender must be pendingAnchorAdmin\n     * @dev Admin function for pending anchor admin to accept role and update anchor admin\n     * @return uint 0=success, otherwise a failure\n     */\n    function _acceptAnchorAdmin() public returns (uint256) {\n        // Check caller = pendingAnchorAdmin\n        // msg.sender can't be zero\n        if (msg.sender != pendingAnchorAdmin) {\n            return\n                failOracle(\n                    address(0),\n                    OracleError.UNAUTHORIZED,\n                    OracleFailureInfo\n                        .ACCEPT_ANCHOR_ADMIN_PENDING_ANCHOR_ADMIN_CHECK\n                );\n        }\n\n        // Save current value for inclusion in log\n        address oldAnchorAdmin = anchorAdmin;\n        // Store admin = pendingAnchorAdmin\n        anchorAdmin = pendingAnchorAdmin;\n        // Clear the pending value\n        pendingAnchorAdmin = address(0);\n\n        emit NewAnchorAdmin(oldAnchorAdmin, msg.sender);\n\n        return uint256(Error.NO_ERROR);\n    }\n\n    /**\n     * @notice retrieves price of an asset\n     * @dev function to get price for an asset\n     * @param asset Asset for which to get the price\n     * @return uint mantissa of asset price (scaled by 1e18) or zero if unset or contract paused\n     */\n    function assetPrices(address asset) public view returns (uint256) {\n        // Note: zero is treated by the money market as an invalid\n        //       price and will cease operations with that asset\n        //       when zero.\n        //\n        // We get the price as:\n        //\n        //  1. If the contract is paused, return 0.\n        //  2. Return price in `_assetPrices`, which may be zero.\n\n        if (paused) {\n            return 0;\n        }\n        return _assetPrices[asset].mantissa;\n    }\n\n    /**\n     * @notice retrieves price of an asset\n     * @dev function to get price for an asset\n     * @param asset Asset for which to get the price\n     * @return uint mantissa of asset price (scaled by 1e18) or zero if unset or contract paused\n     */\n    function getPrice(address asset) public view returns (uint256) {\n        return assetPrices(asset);\n    }\n\n    struct SetPriceLocalVars {\n        Exp price;\n        Exp swing;\n        Exp anchorPrice;\n        uint256 anchorPeriod;\n        uint256 currentPeriod;\n        bool priceCapped;\n        uint256 cappingAnchorPriceMantissa;\n        uint256 pendingAnchorMantissa;\n    }\n\n    /**\n     * @notice entry point for updating prices\n     * @dev function to set price for an asset\n     * @param asset Asset for which to set the price\n     * @param requestedPriceMantissa requested new price, scaled by 10**18\n     * @return uint 0=success, otherwise a failure (see enum OracleError for details)\n     */\n    function setPrice(address asset, uint256 requestedPriceMantissa)\n        public\n        returns (uint256)\n    {\n        // Fail when msg.sender is not poster\n        if (msg.sender != poster) {\n            return\n                failOracle(\n                    asset,\n                    OracleError.UNAUTHORIZED,\n                    OracleFailureInfo.SET_PRICE_PERMISSION_CHECK\n                );\n        }\n\n        return setPriceInternal(asset, requestedPriceMantissa);\n    }\n\n    function setPriceInternal(address asset, uint256 requestedPriceMantissa)\n        internal\n        returns (uint256)\n    {\n        // re-used for intermediate errors\n        Error err;\n        SetPriceLocalVars memory localVars;\n        // We add 1 for currentPeriod so that it can never be zero and there's no ambiguity about an unset value.\n        // (It can be a problem in tests with low block numbers.)\n        localVars.currentPeriod = (block.number / numBlocksPerPeriod) + 1;\n        localVars.pendingAnchorMantissa = pendingAnchors[asset];\n        localVars.price = Exp({mantissa: requestedPriceMantissa});\n\n        if (localVars.pendingAnchorMantissa != 0) {\n            // let's explicitly set to 0 rather than relying on default of declaration\n            localVars.anchorPeriod = 0;\n            localVars.anchorPrice = Exp({\n                mantissa: localVars.pendingAnchorMantissa\n            });\n\n            // Verify movement is within max swing of pending anchor (currently: 10%)\n            (err, localVars.swing) = calculateSwing(\n                localVars.anchorPrice,\n                localVars.price\n            );\n            if (err != Error.NO_ERROR) {\n                return\n                    failOracleWithDetails(\n                        asset,\n                        OracleError.FAILED_TO_SET_PRICE,\n                        OracleFailureInfo.SET_PRICE_CALCULATE_SWING,\n                        uint256(err)\n                    );\n            }\n\n            // Fail when swing > maxSwing\n            if (greaterThanExp(localVars.swing, maxSwing)) {\n                return\n                    failOracleWithDetails(\n                        asset,\n                        OracleError.FAILED_TO_SET_PRICE,\n                        OracleFailureInfo.SET_PRICE_MAX_SWING_CHECK,\n                        localVars.swing.mantissa\n                    );\n            }\n        } else {\n            localVars.anchorPeriod = anchors[asset].period;\n            localVars.anchorPrice = Exp({\n                mantissa: anchors[asset].priceMantissa\n            });\n\n            if (localVars.anchorPeriod != 0) {\n                (err, localVars.priceCapped, localVars.price) = capToMax(\n                    localVars.anchorPrice,\n                    localVars.price\n                );\n                if (err != Error.NO_ERROR) {\n                    return\n                        failOracleWithDetails(\n                            asset,\n                            OracleError.FAILED_TO_SET_PRICE,\n                            OracleFailureInfo.SET_PRICE_CAP_TO_MAX,\n                            uint256(err)\n                        );\n                }\n                if (localVars.priceCapped) {\n                    // save for use in log\n                    localVars.cappingAnchorPriceMantissa = localVars\n                        .anchorPrice\n                        .mantissa;\n                }\n            } else {\n                // Setting first price. Accept as is (already assigned above from requestedPriceMantissa) and use as anchor\n                localVars.anchorPrice = Exp({mantissa: requestedPriceMantissa});\n            }\n        }\n\n        // Fail if anchorPrice or price is zero.\n        // zero anchor represents an unexpected situation likely due to a problem in this contract\n        // zero price is more likely as the result of bad input from the caller of this function\n        if (isZeroExp(localVars.anchorPrice)) {\n            // If we get here price could also be zero, but it does not seem worthwhile to distinguish the 3rd case\n            return\n                failOracle(\n                    asset,\n                    OracleError.FAILED_TO_SET_PRICE,\n                    OracleFailureInfo\n                        .SET_PRICE_NO_ANCHOR_PRICE_OR_INITIAL_PRICE_ZERO\n                );\n        }\n\n        if (isZeroExp(localVars.price)) {\n            return\n                failOracle(\n                    asset,\n                    OracleError.FAILED_TO_SET_PRICE,\n                    OracleFailureInfo.SET_PRICE_ZERO_PRICE\n                );\n        }\n\n        // BEGIN SIDE EFFECTS\n\n        // Set pendingAnchor = Nothing\n        // Pending anchor is only used once.\n        if (pendingAnchors[asset] != 0) {\n            pendingAnchors[asset] = 0;\n        }\n\n        // If currentPeriod > anchorPeriod:\n        //  Set anchors[asset] = (currentPeriod, price)\n        //  The new anchor is if we're in a new period or we had a pending anchor, then we become the new anchor\n        if (localVars.currentPeriod > localVars.anchorPeriod) {\n            anchors[asset] = Anchor({\n                period: localVars.currentPeriod,\n                priceMantissa: localVars.price.mantissa\n            });\n        }\n\n        uint256 previousPrice = _assetPrices[asset].mantissa;\n\n        setPriceStorageInternal(asset, localVars.price.mantissa);\n\n        emit PricePosted(\n            asset,\n            previousPrice,\n            requestedPriceMantissa,\n            localVars.price.mantissa\n        );\n\n        if (localVars.priceCapped) {\n            // We have set a capped price. Log it so we can detect the situation and investigate.\n            emit CappedPricePosted(\n                asset,\n                requestedPriceMantissa,\n                localVars.cappingAnchorPriceMantissa,\n                localVars.price.mantissa\n            );\n        }\n\n        return uint256(OracleError.NO_ERROR);\n    }\n\n    // As a function to allow harness overrides\n    function setPriceStorageInternal(address asset, uint256 priceMantissa)\n        internal\n    {\n        _assetPrices[asset] = Exp({mantissa: priceMantissa});\n    }\n\n    // abs(price - anchorPrice) / anchorPrice\n    function calculateSwing(Exp memory anchorPrice, Exp memory price)\n        internal\n        pure\n        returns (Error, Exp memory)\n    {\n        Exp memory numerator;\n        Error err;\n\n        if (greaterThanExp(anchorPrice, price)) {\n            (err, numerator) = subExp(anchorPrice, price);\n            // can't underflow\n            assert(err == Error.NO_ERROR);\n        } else {\n            (err, numerator) = subExp(price, anchorPrice);\n            // Given greaterThan check above, price >= anchorPrice so can't underflow.\n            assert(err == Error.NO_ERROR);\n        }\n\n        return divExp(numerator, anchorPrice);\n    }\n\n    function capToMax(Exp memory anchorPrice, Exp memory price)\n        internal\n        view\n        returns (\n            Error,\n            bool,\n            Exp memory\n        )\n    {\n        Exp memory one = Exp({mantissa: mantissaOne});\n        Exp memory onePlusMaxSwing;\n        Exp memory oneMinusMaxSwing;\n        Exp memory max;\n        Exp memory min;\n        // re-used for intermediate errors\n        Error err;\n\n        (err, onePlusMaxSwing) = addExp(one, maxSwing);\n        if (err != Error.NO_ERROR) {\n            return (err, false, Exp({mantissa: 0}));\n        }\n\n        // max = anchorPrice * (1 + maxSwing)\n        (err, max) = mulExp(anchorPrice, onePlusMaxSwing);\n        if (err != Error.NO_ERROR) {\n            return (err, false, Exp({mantissa: 0}));\n        }\n\n        // If price > anchorPrice * (1 + maxSwing)\n        // Set price = anchorPrice * (1 + maxSwing)\n        if (greaterThanExp(price, max)) {\n            return (Error.NO_ERROR, true, max);\n        }\n\n        (err, oneMinusMaxSwing) = subExp(one, maxSwing);\n        if (err != Error.NO_ERROR) {\n            return (err, false, Exp({mantissa: 0}));\n        }\n\n        // min = anchorPrice * (1 - maxSwing)\n        (err, min) = mulExp(anchorPrice, oneMinusMaxSwing);\n        // We can't overflow here or we would have already overflowed above when calculating `max`\n        assert(err == Error.NO_ERROR);\n\n        // If  price < anchorPrice * (1 - maxSwing)\n        // Set price = anchorPrice * (1 - maxSwing)\n        if (lessThanExp(price, min)) {\n            return (Error.NO_ERROR, true, min);\n        }\n\n        return (Error.NO_ERROR, false, price);\n    }\n\n    /**\n     * @notice entry point for updating multiple prices\n     * @dev function to set prices for a variable number of assets.\n     * @param assets a list of up to assets for which to set a price. required: 0 < assets.length == requestedPriceMantissas.length\n     * @param requestedPriceMantissas requested new prices for the assets, scaled by 10**18. required: 0 < assets.length == requestedPriceMantissas.length\n     * @return uint values in same order as inputs. For each: 0=success, otherwise a failure (see enum OracleError for details)\n     */\n    function setPrices(\n        address[] memory assets,\n        uint256[] memory requestedPriceMantissas\n    ) public returns (uint256[] memory) {\n        uint256 numAssets = assets.length;\n        uint256 numPrices = requestedPriceMantissas.length;\n        uint256[] memory result;\n\n        // Fail when msg.sender is not poster\n        if (msg.sender != poster) {\n            result = new uint256[](1);\n            result[0] = failOracle(\n                address(0),\n                OracleError.UNAUTHORIZED,\n                OracleFailureInfo.SET_PRICE_PERMISSION_CHECK\n            );\n            return result;\n        }\n\n        if ((numAssets == 0) || (numPrices != numAssets)) {\n            result = new uint256[](1);\n            result[0] = failOracle(\n                address(0),\n                OracleError.FAILED_TO_SET_PRICE,\n                OracleFailureInfo.SET_PRICES_PARAM_VALIDATION\n            );\n            return result;\n        }\n\n        result = new uint256[](numAssets);\n\n        for (uint256 i = 0; i < numAssets; i++) {\n            result[i] = setPriceInternal(assets[i], requestedPriceMantissas[i]);\n        }\n\n        return result;\n    }\n}"
      }
    },
    "settings": {
      "remappings": [
        "@blueberry/=lib/blueberry-core/contracts/",
        "@blueberry-stakevest/=lib/blueberry-stakevest/src/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
        "@openzeppelin/contracts-upgradeable/=lib/blueberry-core/node_modules/@openzeppelin/contracts-upgradeable/",
        "src/=src/BlueberryContracts/",
        "openzeppelin-contracts-upgradeable/contracts/=lib/blueberry-stakevest/lib/openzeppelin-contracts-upgradeable/contracts/",
        "solady/=lib/blueberry-stakevest/lib/solady/",
        "@chainlink/=lib/blueberry-core/node_modules/@chainlink/",
        "@aave/=lib/blueberry-core/node_modules/@aave/",
        "@contracts/=lib/blueberry-core/contracts/",
        "@eth-optimism/=lib/blueberry-core/node_modules/@eth-optimism/contracts/",
        "@test/=lib/blueberry-core/test/foundry/",
        "@uniswap/=lib/blueberry-core/node_modules/@uniswap/",
        "base64-sol/=lib/blueberry-core/node_modules/base64-sol/",
        "blueberry-core/=lib/blueberry-core/",
        "blueberry-stakevest/=lib/blueberry-stakevest/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
        "eth-gas-reporter/=lib/blueberry-core/node_modules/eth-gas-reporter/",
        "forge-std/=lib/forge-std/src/",
        "hardhat-deploy/=lib/blueberry-core/node_modules/hardhat-deploy/",
        "hardhat/=lib/blueberry-core/node_modules/hardhat/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin-foundry-upgrades/=lib/openzeppelin-foundry-upgrades/src/",
        "openzeppelin/=lib/blueberry-stakevest/lib/openzeppelin-contracts-upgradeable/contracts/",
        "solidity-stringutils/=lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/",
        "v3-core/=lib/blueberry-stakevest/lib/v3-core/contracts/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "istanbul",
      "libraries": {}
    }
  }}