creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/ChainlinkOvalImmutable.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.17;\n\nimport {ImmutableController} from \"oval/src/controllers/ImmutableController.sol\";\nimport {ChainlinkSourceAdapter} from \"oval/src/adapters/source-adapters/ChainlinkSourceAdapter.sol\";\nimport {ChainlinkDestinationAdapter} from \"oval/src/adapters/destination-adapters/ChainlinkDestinationAdapter.sol\";\nimport {IAggregatorV3Source} from \"oval/src/interfaces/chainlink/IAggregatorV3Source.sol\";\n\n/**\n * @title OvalOracle instance that has input and output adapters of Chainlink and ImmutableController.\n */\ncontract ChainlinkOvalImmutable is ImmutableController, ChainlinkSourceAdapter, ChainlinkDestinationAdapter {\n    constructor(\n        IAggregatorV3Source source, // The input chainlink source\n        uint8 decimals, // The number of decimals the input should provide.\n        uint256 lockWindow, // How long the permissioned actor has after each update to run an OEV auction.\n        uint256 maxTraversal, // The maximum lookback traversal limit when looking for historic data.\n        address[] memory unlockers // A set of unlockers who can initiate OEV auctions.\n    )\n        ChainlinkSourceAdapter(source)\n        ImmutableController(lockWindow, maxTraversal, unlockers)\n        ChainlinkDestinationAdapter(decimals)\n    {}\n}\n"
      },
      "lib/oval-contracts/src/controllers/ImmutableController.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\nimport {OVAL} from \"../Oval.sol\";\n\n/**\n * @title ImmutableController providing an immutable controller.\n * @dev The benefit of this controller is two-fold:\n * 1. Permissioning and parameters _cannot_ be updated after deployment. Ownership doesn't exist.\n * 2. Because LOCK_WINDOW and MAX_TRAVERSAL are immutable, the read costs are much lower in the \"hot\" path (end\n *    oracle users).\n */\n\nabstract contract ImmutableController is OVAL {\n    uint256 private immutable LOCK_WINDOW; // The lockWindow in seconds.\n    uint256 private immutable MAX_TRAVERSAL; // The maximum number of rounds to traverse when looking for historical data.\n\n    mapping(address => bool) public unlockers;\n\n    constructor(uint256 _lockWindow, uint256 _maxTraversal, address[] memory _unlockers) {\n        LOCK_WINDOW = _lockWindow;\n        MAX_TRAVERSAL = _maxTraversal;\n        for (uint256 i = 0; i < _unlockers.length; i++) {\n            unlockers[_unlockers[i]] = true;\n\n            emit UnlockerSet(_unlockers[i], true);\n        }\n\n        emit LockWindowSet(_lockWindow);\n        emit MaxTraversalSet(_maxTraversal);\n    }\n\n    /**\n     * @notice Returns true if the caller is allowed to unlock the OVAL.\n     * @dev This implementation simply checks if the caller is in the unlockers mapping. Custom Controllers can override\n     * this function to provide more granular control over who can unlock the OVAL.\n     * @param caller The address to check.\n     * @param _lastUnlockTime The timestamp of the latest unlock to the OVAL. Might be useful in verification.\n     */\n    function canUnlock(address caller, uint256 _lastUnlockTime) public view override returns (bool) {\n        return unlockers[caller];\n    }\n\n    /**\n     * @notice Time window that bounds how long the permissioned actor has to call the unlockLatestValue function after\n     * a new source update is posted. If the permissioned actor does not call unlockLatestValue within this window of a\n     * new source price, the latest value will be made available to everyone without going through an MEV-Share auction.\n     * @return lockWindow time in seconds.\n     */\n    function lockWindow() public view override returns (uint256) {\n        return LOCK_WINDOW;\n    }\n\n    /**\n     * @notice Max number of historical source updates to traverse when looking for a historic value in the past.\n     * @return maxTraversal max number of historical source updates to traverse.\n     */\n    function maxTraversal() public view override returns (uint256) {\n        return MAX_TRAVERSAL;\n    }\n}\n"
      },
      "lib/oval-contracts/src/adapters/source-adapters/ChainlinkSourceAdapter.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\nimport {DecimalLib} from \"../lib/DecimalLib.sol\";\nimport {IAggregatorV3Source} from \"../../interfaces/chainlink/IAggregatorV3Source.sol\";\nimport {DiamondRootOVAL} from \"../../DiamondRootOval.sol\";\n\n/**\n * @title ChainlinkSourceAdapter contract to read data from Chainlink aggregator and standardize it for OVAL.\n * @dev Can fetch information from Chainlink source at a desired timestamp for historic lookups.\n */\n\nabstract contract ChainlinkSourceAdapter is DiamondRootOVAL {\n    IAggregatorV3Source public immutable CHAINLINK_SOURCE;\n    uint8 private immutable SOURCE_DECIMALS;\n\n    // As per Chainlink documentation https://docs.chain.link/data-feeds/historical-data#roundid-in-proxy\n    // roundId on the aggregator proxy is comprised of phaseId (higher 16 bits) and roundId from phase aggregator\n    // (lower 64 bits). PHASE_MASK is used to calculate first roundId of current phase aggregator.\n    uint80 private constant PHASE_MASK = uint80(0xFFFF) << 64;\n\n    event SourceSet(address indexed sourceOracle, uint8 indexed sourceDecimals);\n\n    constructor(IAggregatorV3Source source) {\n        CHAINLINK_SOURCE = source;\n        SOURCE_DECIMALS = source.decimals();\n\n        emit SourceSet(address(source), SOURCE_DECIMALS);\n    }\n\n    /**\n     * @notice Tries getting latest data as of requested timestamp. If this is not possible, returns the earliest data\n     * available past the requested timestamp within provided traversal limitations.\n     * @param timestamp The timestamp to try getting latest data at.\n     * @param maxTraversal The maximum number of rounds to traverse when looking for historical data.\n     * @return answer The answer as of requested timestamp, or earliest available data if not available, in 18 decimals.\n     * @return updatedAt The timestamp of the answer.\n     */\n    function tryLatestDataAt(uint256 timestamp, uint256 maxTraversal)\n        public\n        view\n        virtual\n        override\n        returns (int256, uint256)\n    {\n        (int256 answer, uint256 updatedAt) = _tryLatestRoundDataAt(timestamp, maxTraversal);\n        return (DecimalLib.convertDecimals(answer, SOURCE_DECIMALS, 18), updatedAt);\n    }\n\n    /**\n     * @notice Initiate a snapshot of the source data. This is a no-op for Chainlink.\n     */\n    function snapshotData() public virtual override {}\n\n    /**\n     * @notice Returns the latest data from the source.\n     * @return answer The latest answer in 18 decimals.\n     * @return updatedAt The timestamp of the answer.\n     */\n    function getLatestSourceData() public view virtual override returns (int256, uint256) {\n        (, int256 sourceAnswer,, uint256 updatedAt,) = CHAINLINK_SOURCE.latestRoundData();\n        return (DecimalLib.convertDecimals(sourceAnswer, SOURCE_DECIMALS, 18), updatedAt);\n    }\n\n    // Tries getting latest data as of requested timestamp. If this is not possible, returns the earliest data available\n    // past the requested timestamp considering the maxTraversal limitations.\n    function _tryLatestRoundDataAt(uint256 timestamp, uint256 maxTraversal) internal view returns (int256, uint256) {\n        (uint80 roundId, int256 answer,, uint256 updatedAt,) = CHAINLINK_SOURCE.latestRoundData();\n\n        // In the happy path there have been no source updates since requested time, so we can return the latest data.\n        // We can use updatedAt property as it matches the block timestamp of the latest source transmission.\n        if (updatedAt <= timestamp) return (answer, updatedAt);\n\n        // Attempt traversing historical round data backwards from roundId. This might still be newer or uninitialized.\n        (int256 historicalAnswer, uint256 historicalUpdatedAt) = _searchRoundDataAt(timestamp, roundId, maxTraversal);\n\n        // Validate returned data. If it is uninitialized we fallback to returning the current latest round data.\n        if (historicalUpdatedAt > 0) return (historicalAnswer, historicalUpdatedAt);\n        return (answer, updatedAt);\n    }\n\n    // Tries finding latest historical data (ignoring current roundId) not newer than requested timestamp. Might return\n    // newer data than requested if exceeds traversal or hold uninitialized data that should be handled by the caller.\n    function _searchRoundDataAt(uint256 timestamp, uint80 targetRoundId, uint256 maxTraversal)\n        internal\n        view\n        returns (int256, uint256)\n    {\n        uint80 roundId;\n        int256 answer;\n        uint256 updatedAt;\n        uint80 traversedRounds = 0;\n        uint80 startRoundId = (targetRoundId & PHASE_MASK) + 1; // Phase aggregators are starting at round 1.\n\n        while (traversedRounds < uint80(maxTraversal) && targetRoundId > startRoundId) {\n            targetRoundId--; // We started from latest roundId that should be ignored.\n            // The aggregator proxy does not keep track when its phase aggregators got switched. This means that we can\n            // only traverse rounds of the current phase aggregator. When phase aggregators are switched there is\n            // normally an overlap period when both new and old phase aggregators receive updates. Without knowing exact\n            // time when the aggregator proxy switched them we might end up returning historical data from the new phase\n            // aggregator that was not yet available on the aggregator proxy at the requested timestamp.\n\n            (roundId, answer,, updatedAt,) = CHAINLINK_SOURCE.getRoundData(targetRoundId);\n            if (!(roundId == targetRoundId && updatedAt > 0)) return (0, 0);\n            if (updatedAt <= timestamp) return (answer, updatedAt);\n            traversedRounds++;\n        }\n\n        return (answer, updatedAt); // Did not find requested round. Return earliest round or uninitialized data.\n    }\n}\n"
      },
      "lib/oval-contracts/src/adapters/destination-adapters/ChainlinkDestinationAdapter.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\nimport {DecimalLib} from \"../lib/DecimalLib.sol\";\nimport {IAggregatorV3} from \"../../interfaces/chainlink/IAggregatorV3.sol\";\nimport {DiamondRootOVAL} from \"../../DiamondRootOval.sol\";\n\n/**\n * @title ChainlinkDestinationAdapter contract to expose OVAL data via the standard Chainlink Aggregator interface.\n */\n\nabstract contract ChainlinkDestinationAdapter is DiamondRootOVAL, IAggregatorV3 {\n    uint8 public immutable override decimals;\n\n    event DecimalsSet(uint8 indexed decimals);\n\n    constructor(uint8 _decimals) {\n        decimals = _decimals;\n\n        emit DecimalsSet(_decimals);\n    }\n\n    /**\n     * @notice Returns the latest data from the source.\n     * @return answer The latest answer in the configured number of decimals.\n     */\n    function latestAnswer() public view override returns (int256) {\n        (int256 answer,) = internalLatestData();\n        return DecimalLib.convertDecimals(answer, 18, decimals);\n    }\n\n    /**\n     * @notice Returns when the latest answer was updated.\n     * @return timestamp The timestamp of the latest answer.\n     */\n    function latestTimestamp() public view override returns (uint256) {\n        (, uint256 timestamp) = internalLatestData();\n        return timestamp;\n    }\n\n    /**\n     * @notice Returns an approximate form of the latest Round data. This does not implement the notion of \"roundId\" that\n     * the normal chainlink aggregator does and returns hardcoded values for those fields.\n     * @return roundId The roundId of the latest answer, hardcoded to 1.\n     * @return answer The latest answer in the configured number of decimals.\n     * @return startedAt The timestamp when the value was updated.\n     * @return updatedAt The timestamp when the value was updated.\n     * @return answeredInRound The roundId of the round in which the answer was computed, hardcoded to 1.\n     */\n    function latestRoundData() external view returns (uint80, int256, uint256, uint256, uint80) {\n        (int256 answer, uint256 updatedAt) = internalLatestData();\n        return (1, DecimalLib.convertDecimals(answer, 18, decimals), updatedAt, updatedAt, 1);\n    }\n}\n"
      },
      "lib/oval-contracts/src/interfaces/chainlink/IAggregatorV3Source.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\ninterface IAggregatorV3Source {\n    function decimals() external view returns (uint8);\n\n    function latestRoundData()\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n    function getRoundData(uint80 _roundId)\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n}\n"
      },
      "lib/oval-contracts/src/Oval.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\nimport {Math} from \"openzeppelin-contracts/contracts/utils/math/Math.sol\";\nimport {DiamondRootOVAL} from \"./DiamondRootOval.sol\";\n\n/**\n * @title OVAL contract to provide permissioned updating at the execution of an MEV-share auction.\n * @dev This contract works by conditionally returning a stale value oracle price from the source adapter until a\n * permissioned actor calls the unlockLatestValue function. The call to unlockLatestValue is submitted via an MEV-share\n * auction and will be backrun by the winner of the auction. The backrunner has access to the most recent newly unlocked\n * source price. If someone tries to front-run the call to unlockLatestValue, the caller will receive a stale value. If\n * the permissioned actor does not call unlockLatestValue within the lockWindow, the latest value that is at least\n * lockWindow seconds old will be returned. This contract is intended to be used in conjunction with a Controller\n * contract that governs who can call unlockLatestValue.\n * @custom:security-contact bugs@umaproject.org\n */\n\nabstract contract OVAL is DiamondRootOVAL {\n    uint256 public lastUnlockTime; // Timestamp of the latest unlock to the OVAL.\n\n    /**\n     * @notice Function called by permissioned actor to unlock the latest value as part of the MEV-share auction flow.\n     * @dev The call to this function is expected to be sent to flashbots via eth_sendPrivateTransaction. This is the\n     * transaction that is backrun by the winner of the auction. The backrunner has access to the most recent newly\n     * unlocked source price as a result and therefore can extract the MEV associated with the unlock.\n     */\n    function unlockLatestValue() public {\n        require(canUnlock(msg.sender, lastUnlockTime), \"Controller blocked: canUnlock\");\n\n        snapshotData(); // If the source connected to this OVAL needs to snapshot data, do it here. Else, no op.\n\n        lastUnlockTime = block.timestamp;\n\n        emit LatestValueUnlocked(block.timestamp);\n    }\n\n    /**\n     * @notice Returns latest data from source, governed by lockWindow controlling if returned data is stale.\n     * @return answer The latest answer in 18 decimals.\n     * @return timestamp The timestamp of the answer.\n     */\n    function internalLatestData() public view override returns (int256, uint256) {\n        // Case work:\n        //-> If unlockLatestValue has been called within lockWindow, then return most recent price as of unlockLatestValue call.\n        //-> If unlockLatestValue has not been called in lockWindow, then return most recent value that is at least lockWindow old.\n        return tryLatestDataAt(Math.max(lastUnlockTime, block.timestamp - lockWindow()), maxTraversal());\n    }\n}\n"
      },
      "lib/oval-contracts/src/adapters/lib/DecimalLib.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\nimport {Math} from \"openzeppelin-contracts/contracts/utils/math/Math.sol\";\n\n/**\n * @title DecimalLib library to perform decimal math operations.\n */\nlibrary DecimalLib {\n    /**\n     * Converts int256 answer scaled at iDecimals to scale at oDecimals.\n     * Source oracle adapters should pass 18 for oDecimals, while destination adapters should pass 18 for iDecimals.\n     * Warning: When downscaling (i.e., when iDecimals > oDecimals), the conversion can lead to a loss of precision.\n     * In the worst case, if the answer is small enough, the conversion can return zero.\n     * Warning: When upscaling (i.e., when iDecimals < oDecimals), if answer * 10^(oDecimals - iDecimals) exceeds\n     * the maximum int256 value, this function will revert. Ensure the provided values will not cause an overflow.\n     */\n    function convertDecimals(int256 answer, uint8 iDecimals, uint8 oDecimals) internal pure returns (int256) {\n        if (iDecimals == oDecimals) return answer;\n        if (iDecimals < oDecimals) return answer * int256(10 ** (oDecimals - iDecimals));\n        return answer / int256(10 ** (iDecimals - oDecimals));\n    }\n\n    /**\n     * Converts uint256 answer scaled at iDecimals to scale at oDecimals.\n     * Source oracle adapters should pass 18 for oDecimals, while destination adapters should pass 18 for iDecimals.\n     * Warning: When downscaling (i.e., when iDecimals > oDecimals), the conversion can lead to a loss of precision.\n     * In the worst case, if the answer is small enough, the conversion can return zero.\n     * Warning: When upscaling (i.e., when iDecimals < oDecimals), if answer * 10^(oDecimals - iDecimals) exceeds\n     * the maximum uint256 value, this function will revert. Ensure the provided values will not cause an overflow.\n     */\n    function convertDecimals(uint256 answer, uint8 iDecimals, uint8 oDecimals) internal pure returns (uint256) {\n        if (iDecimals == oDecimals) return answer;\n        if (iDecimals < oDecimals) return answer * 10 ** (oDecimals - iDecimals);\n        return answer / 10 ** (iDecimals - oDecimals);\n    }\n\n    // Derives token decimals from its scaling factor.\n    function deriveDecimals(uint256 scalingFactor) internal pure returns (uint8) {\n        uint256 decimals = Math.log10(scalingFactor);\n\n        // Verify that the inverse operation yields the expected result.\n        require(10 ** decimals == scalingFactor, \"Invalid scalingFactor\");\n\n        // Note: decimals must fit within uint8 because:\n        // 2^8 = 256, which is uint8 max.\n        // This would imply an input scaling factor of 1e256. The max value of uint256 is \\(2^{256} - 1\\), which is approximately\n        // 1.2e77, but not equal to 1e256. Therefore, decimals will always fit within uint8 or the check above will fail.\n        return uint8(decimals);\n    }\n}\n"
      },
      "lib/oval-contracts/src/DiamondRootOval.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\nimport {IBaseOracleAdapter} from \"./interfaces/IBaseOracleAdapter.sol\";\nimport {IBaseController} from \"./interfaces/IBaseController.sol\";\nimport {IOVAL} from \"./interfaces/IOval.sol\";\n\n/**\n * @title DiamondRootOVAL contract to provide base functions that the three components of the OVAL contract system\n * need. They are exposed here to simplify the inheritance structure of the OVAL contract system and to enable easier\n * composability and extensibility at the integration layer, enabling arbitrary combinations of sources and destinations.\n */\n\nabstract contract DiamondRootOVAL is IBaseController, IOVAL, IBaseOracleAdapter {\n    /**\n     * @notice Returns the latest data from the source.\n     * @return answer The latest answer in 18 decimals.\n     * @return updatedAt The timestamp of the answer.\n     */\n    function getLatestSourceData() public view virtual returns (int256, uint256);\n\n    /**\n     * @notice Tries getting latest data as of requested timestamp. If this is not possible, returns the earliest data\n     * available past the requested timestamp within provided traversal limitations.\n     * @param timestamp The timestamp to try getting latest data at.\n     * @param maxTraversal The maximum number of rounds to traverse when looking for historical data.\n     * @return answer The answer as of requested timestamp, or earliest available data if not available, in 18 decimals.\n     * @return updatedAt The timestamp of the answer.\n     */\n    function tryLatestDataAt(uint256 timestamp, uint256 maxTraversal) public view virtual returns (int256, uint256);\n\n    /**\n     * @notice Returns the latest data from the source. Depending on when the OVAL was last unlocked this might\n     * return an slightly stale value to protect the OEV from being stolen by a front runner.\n     * @return answer The latest answer in 18 decimals.\n     * @return updatedAt The timestamp of the answer.\n     */\n    function internalLatestData() public view virtual returns (int256, uint256);\n\n    /**\n     * @notice Snapshot the current source data. Is a no-op if the source does not require snapshotting.\n     */\n    function snapshotData() public virtual;\n\n    /**\n     * @notice Permissioning function to control who can unlock the OVAL.\n     */\n    function canUnlock(address caller, uint256 cachedLatestTimestamp) public view virtual returns (bool);\n\n    /**\n     * @notice Time window that bounds how long the permissioned actor has to call the unlockLatestValue function after\n     * a new source update is posted. If the permissioned actor does not call unlockLatestValue within this window of a\n     * new source price, the latest value will be made available to everyone without going through an MEV-Share auction.\n     * @return lockWindow time in seconds.\n     */\n    function lockWindow() public view virtual returns (uint256);\n\n    /**\n     * @notice Max number of historical source updates to traverse when looking for a historic value in the past.\n     * @return maxTraversal max number of historical source updates to traverse.\n     */\n    function maxTraversal() public view virtual returns (uint256);\n}\n"
      },
      "lib/oval-contracts/src/interfaces/chainlink/IAggregatorV3.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\ninterface IAggregatorV3 {\n    function latestAnswer() external view returns (int256);\n\n    function latestTimestamp() external view returns (uint256);\n\n    function decimals() external view returns (uint8);\n\n    function latestRoundData()\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n    // Other Chainlink functions we don't need.\n\n    // function latestRound() external view returns (uint256);\n\n    // function getAnswer(uint256 roundId) external view returns (int256);\n\n    // function getTimestamp(uint256 roundId) external view returns (uint256);\n\n    // function description() external view returns (string memory);\n\n    // function version() external view returns (uint256);\n\n    // function getRoundData(uint80 _roundId)\n    //     external\n    //     view\n    //     returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n    // event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);\n\n    // event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);\n}\n"
      },
      "lib/oval-contracts/lib/openzeppelin-contracts/contracts/utils/math/Math.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, \"Math: mulDiv overflow\");\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10 ** 64) {\n                value /= 10 ** 64;\n                result += 64;\n            }\n            if (value >= 10 ** 32) {\n                value /= 10 ** 32;\n                result += 32;\n            }\n            if (value >= 10 ** 16) {\n                value /= 10 ** 16;\n                result += 16;\n            }\n            if (value >= 10 ** 8) {\n                value /= 10 ** 8;\n                result += 8;\n            }\n            if (value >= 10 ** 4) {\n                value /= 10 ** 4;\n                result += 4;\n            }\n            if (value >= 10 ** 2) {\n                value /= 10 ** 2;\n                result += 2;\n            }\n            if (value >= 10 ** 1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);\n        }\n    }\n}\n"
      },
      "lib/oval-contracts/src/interfaces/IBaseOracleAdapter.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\ninterface IBaseOracleAdapter {\n    function tryLatestDataAt(uint256 _timestamp, uint256 _maxTraversal)\n        external\n        view\n        returns (int256 answer, uint256 timestamp);\n\n    function getLatestSourceData() external view returns (int256 answer, uint256 timestamp);\n}\n"
      },
      "lib/oval-contracts/src/interfaces/IBaseController.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\ninterface IBaseController {\n    event LockWindowSet(uint256 indexed lockWindow);\n    event MaxTraversalSet(uint256 indexed maxTraversal);\n    event UnlockerSet(address indexed unlocker, bool indexed allowed);\n\n    function canUnlock(address caller, uint256 cachedLatestTimestamp) external view returns (bool);\n}\n"
      },
      "lib/oval-contracts/src/interfaces/IOval.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity 0.8.17;\n\ninterface IOVAL {\n    event LatestValueUnlocked(uint256 indexed timestamp);\n\n    function internalLatestData() external view returns (int256 answer, uint256 timestamp);\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "oval/=lib/oval-contracts/",
        "openzeppelin-contracts/=lib/oval-contracts/lib/openzeppelin-contracts/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/oval-contracts/lib/openzeppelin-contracts/lib/erc4626-tests/",
        "forge-std/=lib/forge-std/src/",
        "openzeppelin/=lib/oval-contracts/lib/openzeppelin-contracts/contracts/",
        "oval-contracts/=lib/oval-contracts/src/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs"
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "london",
      "libraries": {}
    }
  }}