creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/contracts/EzEthTokenDualOracle.sol": {
        "content": "// SPDX-License-Identifier: ISC\npragma solidity ^0.8.19;\n\n// ====================================================================\n// |     ______                   _______                             |\n// |    / _____________ __  __   / ____(_____  ____ _____  ________   |\n// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \\/ __ `/ __ \\/ ___/ _ \\  |\n// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |\n// | /_/   /_/   \\__,_/_/|_|  /_/   /_/_/ /_/\\__,_/_/ /_/\\___/\\___/   |\n// |                                                                  |\n// ====================================================================\n// ========================== EzEthDualOracle ==========================\n// ====================================================================\n// Frax Finance: https://github.com/FraxFinance\n\n// ====================================================================\n\nimport { Timelock2Step } from \"frax-std/access-control/v1/Timelock2Step.sol\";\nimport { ITimelock2Step } from \"frax-std/access-control/v1/interfaces/ITimelock2Step.sol\";\nimport { UniswapV3SingleTwapOracle, ConstructorParams as UniswapV3SingleTwapOracleParams } from \"./abstracts/UniswapV3SingleTwapOracle.sol\";\nimport { ChainlinkOracleWithMaxDelay, ConstructorParams as ChainlinkOracleWithMaxDelayParams } from \"./abstracts/ChainlinkOracleWithMaxDelay.sol\";\nimport { EthUsdChainlinkOracleWithMaxDelay, ConstructorParams as EthUsdChainlinkOracleWithMaxDelayParams } from \"./abstracts/EthUsdChainlinkOracleWithMaxDelay.sol\";\nimport { DualOracleBase, ConstructorParams as DualOracleBaseParams } from \"./DualOracleBase.sol\";\nimport \"interfaces/IDualOracle.sol\";\n\nstruct ConstructorParams {\n    address ezEthErc20;\n    address wethErc20;\n    address ezEthChainlinkFeed;\n    uint256 maximumOracleDelay;\n    address ethUsdChainlinkFeed;\n    uint256 maxEthUsdOracleDelay;\n    address uniV3PairAddress;\n    uint32 twapDuration;\n    address timelockAddress;\n}\n\ncontract EzEthTokenDualOracle is\n    DualOracleBase,\n    Timelock2Step,\n    UniswapV3SingleTwapOracle,\n    ChainlinkOracleWithMaxDelay,\n    EthUsdChainlinkOracleWithMaxDelay\n{\n    address public immutable EZETH_ERC20;\n\n    constructor(\n        ConstructorParams memory _params\n    )\n        DualOracleBase(\n            DualOracleBaseParams({\n                baseToken0: address(840),\n                baseToken0Decimals: 18,\n                quoteToken0: _params.ezEthErc20,\n                quoteToken0Decimals: 18,\n                baseToken1: address(840),\n                baseToken1Decimals: 18,\n                quoteToken1: _params.ezEthErc20,\n                quoteToken1Decimals: 18\n            })\n        )\n        Timelock2Step()\n        UniswapV3SingleTwapOracle(\n            UniswapV3SingleTwapOracleParams({\n                uniswapV3PairAddress: _params.uniV3PairAddress,\n                twapDuration: _params.twapDuration,\n                baseToken: _params.wethErc20,\n                quoteToken: _params.ezEthErc20\n            })\n        )\n        ChainlinkOracleWithMaxDelay(\n            ChainlinkOracleWithMaxDelayParams({\n                chainlinkFeedAddress: _params.ezEthChainlinkFeed,\n                maximumOracleDelay: _params.maximumOracleDelay\n            })\n        )\n        EthUsdChainlinkOracleWithMaxDelay(\n            EthUsdChainlinkOracleWithMaxDelayParams({\n                ethUsdChainlinkFeedAddress: _params.ethUsdChainlinkFeed,\n                maxEthUsdOracleDelay: _params.maxEthUsdOracleDelay\n            })\n        )\n    {\n        _setTimelock({ _newTimelock: _params.timelockAddress });\n        _registerInterface({ interfaceId: type(IDualOracle).interfaceId });\n        _registerInterface({ interfaceId: type(ITimelock2Step).interfaceId });\n\n        EZETH_ERC20 = _params.ezEthErc20;\n    }\n\n    // ====================================================================\n    // View Helpers\n    // ====================================================================\n\n    function name() external pure returns (string memory) {\n        return \"EzEth Token Dual Oracle Chainlink with Staleness Check and Uniswap V3 TWAP\";\n    }\n\n    // ====================================================================\n    // Configuration Setters\n    // ====================================================================\n\n    /// @notice The ```setMaximumOracleDelay``` function sets the max oracle delay to determine if Chainlink data is stale\n    /// @dev Requires msg.sender to be the timelock address\n    /// @param _newMaxOracleDelay The new max oracle delay\n    function setMaximumOracleDelay(uint256 _newMaxOracleDelay) external override {\n        _requireTimelock();\n        _setMaximumOracleDelay({ _newMaxOracleDelay: _newMaxOracleDelay });\n    }\n\n    /// @notice The ```setMaximumEthUsdOracleDelay``` function set the max oracle delay for the Eth/USD Chainlink oracle\n    /// @dev Requires msg.sender to be the timelock address\n    /// @param _newMaxOracleDelay The new max oracle delay\n    function setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) external override {\n        _requireTimelock();\n        _setMaximumEthUsdOracleDelay({ _newMaxOracleDelay: _newMaxOracleDelay });\n    }\n\n    /// @notice The ```setTwapDuration``` function sets the twap duration for the Uniswap V3 TWAP oracle\n    /// @dev Requires msg.sender to be the timelock address\n    /// @param _newTwapDuration The new twap duration\n    function setTwapDuration(uint32 _newTwapDuration) external override {\n        _requireTimelock();\n        _setTwapDuration({ _newTwapDuration: _newTwapDuration });\n    }\n\n    // ====================================================================\n    // Price Functions\n    // ====================================================================\n\n    /// @notice The ```getEzEthPerUsdTwap``` function returns EzEth per USD using the Uniswap V3 TWAP oracle & Chainlink\n    /// @return _isBadData If the Chainlink oracle is stale\n    /// @return _ezEthPerUsd The EzEth per USD price\n    function getEzEthPerUsdTwap() public view returns (bool _isBadData, uint256 _ezEthPerUsd) {\n        uint256 _ezEthPerWeth = _getUniswapV3Twap();\n        uint256 _usdPerEth;\n        (_isBadData, , _usdPerEth) = _getEthUsdChainlinkPrice();\n        _ezEthPerUsd = (_ezEthPerWeth * ETH_USD_CHAINLINK_FEED_PRECISION) / _usdPerEth;\n    }\n\n    /// @notice The ```getEzEthPerUsdChainlink``` function returns EzEth per USD using the Chainlink oracle\n    /// @return _isBadData If the Chainlink oracle is stale\n    /// @return _ezEthPerUsd The EzEth per USD price\n    function getEzEthPerUsdChainlink() public view returns (bool _isBadData, uint256 _ezEthPerUsd) {\n        (bool _isBadDataEzEth, , uint256 _ethPerEzEthChainlinkRaw) = _getChainlinkPrice();\n        (bool _isBadDataEth, , uint256 _usdPerEth) = _getEthUsdChainlinkPrice();\n        _isBadData = _isBadDataEzEth || _isBadDataEth;\n        _ethPerEzEthChainlinkRaw = (_ethPerEzEthChainlinkRaw * _usdPerEth) / ETH_USD_CHAINLINK_FEED_PRECISION;\n        _ezEthPerUsd = (ORACLE_PRECISION * CHAINLINK_FEED_PRECISION) / _ethPerEzEthChainlinkRaw;\n    }\n\n    /// @notice The ```getPricesNormalized``` function returns the normalized prices in human readable form\n    /// @return _isBadDataNormal If the Chainlink oracle is stale\n    /// @return _priceLowNormal The normalized low price\n    /// @return _priceHighNormal The normalized high price\n    function getPricesNormalized()\n        external\n        view\n        returns (bool _isBadDataNormal, uint256 _priceLowNormal, uint256 _priceHighNormal)\n    {\n        (bool _isBadData, uint256 _priceLow, uint256 _priceHigh) = _getPrices();\n        _isBadDataNormal = _isBadData;\n\n        _priceLowNormal = NORMALIZATION_0 > 0\n            ? _priceLow * 10 ** uint256(NORMALIZATION_0)\n            : _priceLow / 10 ** (uint256(-NORMALIZATION_0));\n\n        _priceHighNormal = NORMALIZATION_1 > 0\n            ? _priceHigh * 10 ** uint256(NORMALIZATION_1)\n            : _priceHigh / 10 ** (uint256(-NORMALIZATION_1));\n    }\n\n    function _getPrices() internal view returns (bool _isBadData, uint256 _priceLow, uint256 _priceHigh) {\n        (bool _isBadDataTwap, uint256 _ezEthPerUsdTwap) = getEzEthPerUsdTwap();\n\n        (bool _isBadDataChainlink, uint256 _ezEthPerUsdChainlink) = getEzEthPerUsdChainlink();\n\n        _isBadData = _isBadDataChainlink || _isBadDataTwap;\n        _priceLow = _ezEthPerUsdTwap < _ezEthPerUsdChainlink ? _ezEthPerUsdTwap : _ezEthPerUsdChainlink;\n        _priceHigh = _ezEthPerUsdChainlink > _ezEthPerUsdTwap ? _ezEthPerUsdChainlink : _ezEthPerUsdTwap;\n    }\n\n    /// @notice The ```getPrices``` function is intended to return two prices from different oracles\n    /// @return _isBadData is true when data is stale or otherwise bad\n    /// @return _priceLow is the lower of the two prices\n    /// @return _priceHigh is the higher of the two prices\n    function getPrices() external view returns (bool _isBadData, uint256 _priceLow, uint256 _priceHigh) {\n        return _getPrices();\n    }\n}\n"
      },
      "node_modules/frax-standard-solidity/src/access-control/v1/Timelock2Step.sol": {
        "content": "// SPDX-License-Identifier: ISC\npragma solidity >=0.8.0;\n\n// ====================================================================\n// |     ______                   _______                             |\n// |    / _____________ __  __   / ____(_____  ____ _____  ________   |\n// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \\/ __ `/ __ \\/ ___/ _ \\  |\n// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |\n// | /_/   /_/   \\__,_/_/|_|  /_/   /_/_/ /_/\\__,_/_/ /_/\\___/\\___/   |\n// |                                                                  |\n// ====================================================================\n// ========================== Timelock2Step ===========================\n// ====================================================================\n// Frax Finance: https://github.com/FraxFinance\n\n// Primary Author\n// Drake Evans: https://github.com/DrakeEvans\n\n// Reviewers\n// Dennis: https://github.com/denett\n\n// ====================================================================\n\n/// @title Timelock2Step\n/// @author Drake Evans (Frax Finance) https://github.com/drakeevans\n/// @dev Inspired by the OpenZeppelin's Ownable2Step contract\n/// @notice  An abstract contract which contains 2-step transfer and renounce logic for a timelock address\nabstract contract Timelock2Step {\n    /// @notice The pending timelock address\n    address public pendingTimelockAddress;\n\n    /// @notice The current timelock address\n    address public timelockAddress;\n\n    constructor() {\n        timelockAddress = msg.sender;\n    }\n\n    /// @notice Emitted when timelock is transferred\n    error OnlyTimelock();\n\n    /// @notice Emitted when pending timelock is transferred\n    error OnlyPendingTimelock();\n\n    /// @notice The ```TimelockTransferStarted``` event is emitted when the timelock transfer is initiated\n    /// @param previousTimelock The address of the previous timelock\n    /// @param newTimelock The address of the new timelock\n    event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock);\n\n    /// @notice The ```TimelockTransferred``` event is emitted when the timelock transfer is completed\n    /// @param previousTimelock The address of the previous timelock\n    /// @param newTimelock The address of the new timelock\n    event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock);\n\n    /// @notice The ```_isSenderTimelock``` function checks if msg.sender is current timelock address\n    /// @return Whether or not msg.sender is current timelock address\n    function _isSenderTimelock() internal view returns (bool) {\n        return msg.sender == timelockAddress;\n    }\n\n    /// @notice The ```_requireTimelock``` function reverts if msg.sender is not current timelock address\n    function _requireTimelock() internal view {\n        if (msg.sender != timelockAddress) revert OnlyTimelock();\n    }\n\n    /// @notice The ```_isSenderPendingTimelock``` function checks if msg.sender is pending timelock address\n    /// @return Whether or not msg.sender is pending timelock address\n    function _isSenderPendingTimelock() internal view returns (bool) {\n        return msg.sender == pendingTimelockAddress;\n    }\n\n    /// @notice The ```_requirePendingTimelock``` function reverts if msg.sender is not pending timelock address\n    function _requirePendingTimelock() internal view {\n        if (msg.sender != pendingTimelockAddress) revert OnlyPendingTimelock();\n    }\n\n    /// @notice The ```_transferTimelock``` function initiates the timelock transfer\n    /// @dev This function is to be implemented by a public function\n    /// @param _newTimelock The address of the nominated (pending) timelock\n    function _transferTimelock(address _newTimelock) internal {\n        pendingTimelockAddress = _newTimelock;\n        emit TimelockTransferStarted(timelockAddress, _newTimelock);\n    }\n\n    /// @notice The ```_acceptTransferTimelock``` function completes the timelock transfer\n    /// @dev This function is to be implemented by a public function\n    function _acceptTransferTimelock() internal {\n        pendingTimelockAddress = address(0);\n        _setTimelock(msg.sender);\n    }\n\n    /// @notice The ```_setTimelock``` function sets the timelock address\n    /// @dev This function is to be implemented by a public function\n    /// @param _newTimelock The address of the new timelock\n    function _setTimelock(address _newTimelock) internal {\n        emit TimelockTransferred(timelockAddress, _newTimelock);\n        timelockAddress = _newTimelock;\n    }\n\n    /// @notice The ```transferTimelock``` function initiates the timelock transfer\n    /// @dev Must be called by the current timelock\n    /// @param _newTimelock The address of the nominated (pending) timelock\n    function transferTimelock(address _newTimelock) external virtual {\n        _requireTimelock();\n        _transferTimelock(_newTimelock);\n    }\n\n    /// @notice The ```acceptTransferTimelock``` function completes the timelock transfer\n    /// @dev Must be called by the pending timelock\n    function acceptTransferTimelock() external virtual {\n        _requirePendingTimelock();\n        _acceptTransferTimelock();\n    }\n\n    /// @notice The ```renounceTimelock``` function renounces the timelock after setting pending timelock to current timelock\n    /// @dev Pending timelock must be set to current timelock before renouncing, creating a 2-step renounce process\n    function renounceTimelock() external virtual {\n        _requireTimelock();\n        _requirePendingTimelock();\n        _transferTimelock(address(0));\n        _setTimelock(address(0));\n    }\n}\n"
      },
      "node_modules/frax-standard-solidity/src/access-control/v1/interfaces/ITimelock2Step.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >=0.8.0;\n\ninterface ITimelock2Step {\n    event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock);\n    event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock);\n\n    function acceptTransferTimelock() external;\n\n    function pendingTimelockAddress() external view returns (address);\n\n    function renounceTimelock() external;\n\n    function timelockAddress() external view returns (address);\n\n    function transferTimelock(address _newTimelock) external;\n}\n"
      },
      "src/contracts/abstracts/UniswapV3SingleTwapOracle.sol": {
        "content": "// SPDX-License-Identifier: ISC\npragma solidity ^0.8.20;\n\n// ====================================================================\n// |     ______                   _______                             |\n// |    / _____________ __  __   / ____(_____  ____ _____  ________   |\n// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \\/ __ `/ __ \\/ ___/ _ \\  |\n// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |\n// | /_/   /_/   \\__,_/_/|_|  /_/   /_/_/ /_/\\__,_/_/ /_/\\___/\\___/   |\n// |                                                                  |\n// ====================================================================\n// ==================== UniswapV3SingleTwapOracle =====================\n// ====================================================================\n// Frax Finance: https://github.com/FraxFinance\n\n// Author\n// Drake Evans: https://github.com/DrakeEvans\n\n// Reviewers\n// Dennis: https://github.com/denett\n\n// ====================================================================\n\nimport { IStaticOracle } from \"@mean-finance/uniswap-v3-oracle/solidity/interfaces/IStaticOracle.sol\";\nimport { ERC165Storage } from \"src/contracts/utils/ERC165Storage.sol\";\nimport { IUniswapV3SingleTwapOracle } from \"interfaces/oracles/abstracts/IUniswapV3SingleTwapOracle.sol\";\n\nstruct ConstructorParams {\n    address uniswapV3PairAddress;\n    uint32 twapDuration;\n    address baseToken;\n    address quoteToken;\n}\n\n/// @title UniswapV3SingleTwapOracle\n/// @author Drake Evans (Frax Finance) https://github.com/drakeevans\n/// @notice  An oracle for UniV3 Twap prices\nabstract contract UniswapV3SingleTwapOracle is ERC165Storage, IUniswapV3SingleTwapOracle {\n    /// @notice address of the Uniswap V3 pair\n    address public immutable UNI_V3_PAIR_ADDRESS;\n\n    /// @notice The precision of the twap\n    uint128 public constant TWAP_PRECISION = 1e18;\n\n    /// @notice The base token of the twap\n    address public immutable UNISWAP_V3_TWAP_BASE_TOKEN;\n\n    /// @notice The quote token of the twap\n    address public immutable UNISWAP_V3_TWAP_QUOTE_TOKEN;\n\n    /// @notice The duration of the twap\n    uint32 public twapDuration;\n\n    constructor(ConstructorParams memory _params) {\n        _registerInterface({ interfaceId: type(IUniswapV3SingleTwapOracle).interfaceId });\n\n        UNI_V3_PAIR_ADDRESS = _params.uniswapV3PairAddress;\n        twapDuration = _params.twapDuration;\n        UNISWAP_V3_TWAP_BASE_TOKEN = _params.baseToken;\n        UNISWAP_V3_TWAP_QUOTE_TOKEN = _params.quoteToken;\n    }\n\n    /// @notice The ```_setTwapDuration``` function sets duration of the twap\n    /// @param _newTwapDuration The new twap duration\n    function _setTwapDuration(uint32 _newTwapDuration) internal {\n        emit SetTwapDuration({ oldTwapDuration: twapDuration, newTwapDuration: _newTwapDuration });\n        twapDuration = _newTwapDuration;\n    }\n\n    function setTwapDuration(uint32 _newTwapDuration) external virtual;\n\n    /// @notice The ```_getUniswapV3Twap``` function is called to get the twap\n    /// @return _twap The twap price\n    function _getUniswapV3Twap() internal view returns (uint256 _twap) {\n        address[] memory _pools = new address[](1);\n        _pools[0] = UNI_V3_PAIR_ADDRESS;\n\n        _twap = IStaticOracle(0xB210CE856631EeEB767eFa666EC7C1C57738d438).quoteSpecificPoolsWithTimePeriod({\n            baseAmount: TWAP_PRECISION,\n            baseToken: UNISWAP_V3_TWAP_BASE_TOKEN,\n            quoteToken: UNISWAP_V3_TWAP_QUOTE_TOKEN,\n            pools: _pools,\n            period: twapDuration\n        });\n    }\n\n    /// @notice The ```getUniswapV3Twap``` function is called to get the twap\n    /// @return _twap The twap price\n    function getUniswapV3Twap() external view virtual returns (uint256 _twap) {\n        _twap = _getUniswapV3Twap();\n    }\n}\n"
      },
      "src/contracts/abstracts/ChainlinkOracleWithMaxDelay.sol": {
        "content": "// SPDX-License-Identifier: ISC\npragma solidity ^0.8.20;\n\n// ====================================================================\n// |     ______                   _______                             |\n// |    / _____________ __  __   / ____(_____  ____ _____  ________   |\n// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \\/ __ `/ __ \\/ ___/ _ \\  |\n// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |\n// | /_/   /_/   \\__,_/_/|_|  /_/   /_/_/ /_/\\__,_/_/ /_/\\___/\\___/   |\n// |                                                                  |\n// ====================================================================\n// =================== ChainlinkOracleWithMaxDelay ====================\n// ====================================================================\n// Frax Finance: https://github.com/FraxFinance\n\n// Author\n// Drake Evans: https://github.com/DrakeEvans\n\n// Reviewers\n// Dennis: https://github.com/denett\n\n// ====================================================================\n\nimport { AggregatorV3Interface } from \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport { ERC165Storage } from \"src/contracts/utils/ERC165Storage.sol\";\nimport { IChainlinkOracleWithMaxDelay } from \"interfaces/oracles/abstracts/IChainlinkOracleWithMaxDelay.sol\";\n\nstruct ConstructorParams {\n    address chainlinkFeedAddress;\n    uint256 maximumOracleDelay;\n}\n\n/// @title ChainlinkOracleWithMaxDelay\n/// @author Drake Evans (Frax Finance) https://github.com/drakeevans\n/// @notice  An abstract oracle for getting prices from Chainlink\nabstract contract ChainlinkOracleWithMaxDelay is ERC165Storage, IChainlinkOracleWithMaxDelay {\n    /// @notice Chainlink aggregator\n    address public immutable CHAINLINK_FEED_ADDRESS;\n\n    /// @notice Decimals of ETH/USD chainlink feed\n    uint8 public immutable CHAINLINK_FEED_DECIMALS;\n\n    /// @notice Precision of ETH/USD chainlink feed\n    uint256 public immutable CHAINLINK_FEED_PRECISION;\n\n    /// @notice Maximum delay of Chainlink data, after which it is considered stale\n    uint256 public maximumOracleDelay;\n\n    constructor(ConstructorParams memory _params) {\n        _registerInterface({ interfaceId: type(IChainlinkOracleWithMaxDelay).interfaceId });\n\n        CHAINLINK_FEED_ADDRESS = _params.chainlinkFeedAddress;\n        CHAINLINK_FEED_DECIMALS = AggregatorV3Interface(CHAINLINK_FEED_ADDRESS).decimals();\n        CHAINLINK_FEED_PRECISION = 10 ** uint256(CHAINLINK_FEED_DECIMALS);\n        maximumOracleDelay = _params.maximumOracleDelay;\n    }\n\n    /// @notice The ```SetMaximumOracleDelay``` event is emitted when the max oracle delay is set\n    /// @param oldMaxOracleDelay The old max oracle delay\n    /// @param newMaxOracleDelay The new max oracle delay\n    event SetMaximumOracleDelay(uint256 oldMaxOracleDelay, uint256 newMaxOracleDelay);\n\n    /// @notice The ```_setMaximumOracleDelay``` function sets the max oracle delay to determine if Chainlink data is stale\n    /// @param _newMaxOracleDelay The new max oracle delay\n    function _setMaximumOracleDelay(uint256 _newMaxOracleDelay) internal {\n        emit SetMaximumOracleDelay({ oldMaxOracleDelay: maximumOracleDelay, newMaxOracleDelay: _newMaxOracleDelay });\n        maximumOracleDelay = _newMaxOracleDelay;\n    }\n\n    function setMaximumOracleDelay(uint256 _newMaxOracleDelay) external virtual;\n\n    function _getChainlinkPrice() internal view returns (bool _isBadData, uint256 _updatedAt, uint256 _price) {\n        (, int256 _answer, , uint256 _chainlinkUpdatedAt, ) = AggregatorV3Interface(CHAINLINK_FEED_ADDRESS)\n            .latestRoundData();\n\n        // If data is stale or negative, set bad data to true and return\n        _isBadData = _answer <= 0 || ((block.timestamp - _chainlinkUpdatedAt) > maximumOracleDelay);\n        _updatedAt = _chainlinkUpdatedAt;\n        _price = uint256(_answer);\n    }\n\n    /// @notice The ```getChainlinkPrice``` function returns the chainlink price and the timestamp of the last update\n    /// @dev Uses the same prevision as the chainlink feed, virtual so it can be overridden\n    /// @return _isBadData True if the data is stale or negative\n    /// @return _updatedAt The timestamp of the last update\n    /// @return _price The price\n    function getChainlinkPrice() external view virtual returns (bool _isBadData, uint256 _updatedAt, uint256 _price) {\n        return _getChainlinkPrice();\n    }\n}\n"
      },
      "src/contracts/abstracts/EthUsdChainlinkOracleWithMaxDelay.sol": {
        "content": "// SPDX-License-Identifier: ISC\npragma solidity ^0.8.20;\n\n// ====================================================================\n// |     ______                   _______                             |\n// |    / _____________ __  __   / ____(_____  ____ _____  ________   |\n// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \\/ __ `/ __ \\/ ___/ _ \\  |\n// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |\n// | /_/   /_/   \\__,_/_/|_|  /_/   /_/_/ /_/\\__,_/_/ /_/\\___/\\___/   |\n// |                                                                  |\n// ====================================================================\n// ================ EthUsdChainlinkOracleWithMaxDelay =================\n// ====================================================================\n// Frax Finance: https://github.com/FraxFinance\n\n// Author\n// Drake Evans: https://github.com/DrakeEvans\n\n// Reviewers\n// Dennis: https://github.com/denett\n\n// ====================================================================\n\nimport { AggregatorV3Interface } from \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport { ERC165Storage } from \"src/contracts/utils/ERC165Storage.sol\";\nimport { IEthUsdChainlinkOracleWithMaxDelay } from \"interfaces/oracles/abstracts/IEthUsdChainlinkOracleWithMaxDelay.sol\";\n\nstruct ConstructorParams {\n    address ethUsdChainlinkFeedAddress;\n    uint256 maxEthUsdOracleDelay;\n}\n\n/// @title EthUsdChainlinkOracleWithMaxDelay\n/// @author Drake Evans (Frax Finance) https://github.com/drakeevans\n/// @notice  An abstract oracle for getting eth/usd prices from Chainlink\nabstract contract EthUsdChainlinkOracleWithMaxDelay is ERC165Storage, IEthUsdChainlinkOracleWithMaxDelay {\n    /// @notice Chainlink aggregator\n    address public immutable ETH_USD_CHAINLINK_FEED_ADDRESS;\n\n    /// @notice Decimals of ETH/USD chainlink feed\n    uint8 public immutable ETH_USD_CHAINLINK_FEED_DECIMALS;\n\n    /// @notice Precision of ETH/USD chainlink feed\n    uint256 public immutable ETH_USD_CHAINLINK_FEED_PRECISION;\n\n    /// @notice Maximum delay of Chainlink data, after which it is considered stale\n    uint256 public maximumEthUsdOracleDelay;\n\n    constructor(ConstructorParams memory _params) {\n        _registerInterface({ interfaceId: type(IEthUsdChainlinkOracleWithMaxDelay).interfaceId });\n\n        ETH_USD_CHAINLINK_FEED_ADDRESS = _params.ethUsdChainlinkFeedAddress;\n        ETH_USD_CHAINLINK_FEED_DECIMALS = AggregatorV3Interface(ETH_USD_CHAINLINK_FEED_ADDRESS).decimals();\n        ETH_USD_CHAINLINK_FEED_PRECISION = 10 ** uint256(ETH_USD_CHAINLINK_FEED_DECIMALS);\n        maximumEthUsdOracleDelay = _params.maxEthUsdOracleDelay;\n    }\n\n    /// @notice The ```_setMaximumEthUsdOracleDelay``` function sets the max oracle delay to determine if Chainlink data is stale\n    /// @param _newMaxOracleDelay The new max oracle delay\n    function _setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) internal {\n        emit SetMaximumEthUsdOracleDelay({\n            oldMaxOracleDelay: maximumEthUsdOracleDelay,\n            newMaxOracleDelay: _newMaxOracleDelay\n        });\n        maximumEthUsdOracleDelay = _newMaxOracleDelay;\n    }\n\n    function setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) external virtual;\n\n    /// @notice The ```_getEthUsdChainlinkPrice``` function is called to get the eth/usd price from Chainlink\n    /// @dev If data is stale or negative, set bad data to true and return\n    /// @return _isBadData If the data is stale\n    /// @return _updatedAt The timestamp of the last update\n    /// @return _usdPerEth The eth/usd price\n    function _getEthUsdChainlinkPrice()\n        internal\n        view\n        returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth)\n    {\n        (, int256 _answer, , uint256 _ethUsdChainlinkUpdatedAt, ) = AggregatorV3Interface(\n            ETH_USD_CHAINLINK_FEED_ADDRESS\n        ).latestRoundData();\n\n        // If data is stale or negative, set bad data to true and return\n        _isBadData = _answer <= 0 || ((block.timestamp - _ethUsdChainlinkUpdatedAt) > maximumEthUsdOracleDelay);\n        _updatedAt = _ethUsdChainlinkUpdatedAt;\n        _usdPerEth = uint256(_answer);\n    }\n\n    /// @notice The ```getEthUsdChainlinkPrice``` function is called to get the eth/usd price from Chainlink\n    /// @return _isBadData If the data is stale\n    /// @return _updatedAt The timestamp of the last update\n    /// @return _usdPerEth The eth/usd price\n    function getEthUsdChainlinkPrice()\n        external\n        view\n        virtual\n        returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth)\n    {\n        (_isBadData, _updatedAt, _usdPerEth) = _getEthUsdChainlinkPrice();\n    }\n}\n"
      },
      "src/contracts/DualOracleBase.sol": {
        "content": "// SPDX-License-Identifier: ISC\npragma solidity ^0.8.20;\n\n// ====================================================================\n// |     ______                   _______                             |\n// |    / _____________ __  __   / ____(_____  ____ _____  ________   |\n// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \\/ __ `/ __ \\/ ___/ _ \\  |\n// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |\n// | /_/   /_/   \\__,_/_/|_|  /_/   /_/_/ /_/\\__,_/_/ /_/\\___/\\___/   |\n// |                                                                  |\n// ====================================================================\n// ========================== DualOracleBase ==========================\n// ====================================================================\n// Frax Finance: https://github.com/FraxFinance\n\n// Author\n// Drake Evans: https://github.com/DrakeEvans\n\n// ====================================================================\n\nimport \"interfaces/IDualOracle.sol\";\n\nstruct ConstructorParams {\n    address baseToken0;\n    uint8 baseToken0Decimals;\n    address quoteToken0;\n    uint8 quoteToken0Decimals;\n    address baseToken1;\n    uint8 baseToken1Decimals;\n    address quoteToken1;\n    uint8 quoteToken1Decimals;\n}\n\n/// @title DualOracleBase\n/// @author Drake Evans (Frax Finance) https://github.com/drakeevans\n/// @notice  Base Contract for Frax Dual Oracles\nabstract contract DualOracleBase is IDualOracle {\n    /// @notice The precision of the oracle\n    uint256 public constant ORACLE_PRECISION = 1e18;\n\n    /// @notice The first quote token\n    address public immutable QUOTE_TOKEN_0;\n\n    /// @notice The first quote token decimals\n    uint256 public immutable QUOTE_TOKEN_0_DECIMALS;\n\n    /// @notice The second quote token\n    address public immutable QUOTE_TOKEN_1;\n\n    /// @notice The second quote token decimals\n    uint256 public immutable QUOTE_TOKEN_1_DECIMALS;\n\n    /// @notice The first base token\n    address public immutable BASE_TOKEN_0;\n\n    /// @notice The first base token decimals\n    uint256 public immutable BASE_TOKEN_0_DECIMALS;\n\n    /// @notice The second base token\n    address public immutable BASE_TOKEN_1;\n\n    /// @notice The second base token decimals\n    uint256 public immutable BASE_TOKEN_1_DECIMALS;\n\n    /// @notice The first normalization factor which accounts for different decimals across ERC20s\n    /// @dev Normalization = quoteTokenDecimals - baseTokenDecimals\n    int256 public immutable NORMALIZATION_0;\n\n    /// @notice The second normalization factor which accounts for different decimals across ERC20s\n    /// @dev Normalization = quoteTokenDecimals - baseTokenDecimals\n    int256 public immutable NORMALIZATION_1;\n\n    constructor(ConstructorParams memory _params) {\n        QUOTE_TOKEN_0 = _params.quoteToken0;\n        QUOTE_TOKEN_0_DECIMALS = _params.quoteToken0Decimals;\n        QUOTE_TOKEN_1 = _params.quoteToken1;\n        QUOTE_TOKEN_1_DECIMALS = _params.quoteToken1Decimals;\n        BASE_TOKEN_0 = _params.baseToken0;\n        BASE_TOKEN_0_DECIMALS = _params.baseToken0Decimals;\n        BASE_TOKEN_1 = _params.baseToken1;\n        BASE_TOKEN_1_DECIMALS = _params.baseToken1Decimals;\n        NORMALIZATION_0 = int256(QUOTE_TOKEN_0_DECIMALS) - int256(BASE_TOKEN_0_DECIMALS);\n        NORMALIZATION_1 = int256(QUOTE_TOKEN_1_DECIMALS) - int256(BASE_TOKEN_1_DECIMALS);\n    }\n\n    // ====================================================================\n    // View Helpers\n    // ====================================================================\n\n    function decimals() external pure returns (uint8) {\n        return 18;\n    }\n}\n"
      },
      "src/contracts/interfaces/IDualOracle.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.20;\n\nimport \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ninterface IDualOracle is IERC165 {\n    function ORACLE_PRECISION() external view returns (uint256);\n\n    function BASE_TOKEN_0() external view returns (address);\n\n    function BASE_TOKEN_0_DECIMALS() external view returns (uint256);\n\n    function BASE_TOKEN_1() external view returns (address);\n\n    function BASE_TOKEN_1_DECIMALS() external view returns (uint256);\n\n    function decimals() external view returns (uint8);\n\n    function getPricesNormalized() external view returns (bool _isBadData, uint256 _priceLow, uint256 _priceHigh);\n\n    function getPrices() external view returns (bool _isBadData, uint256 _priceLow, uint256 _priceHigh);\n\n    function name() external view returns (string memory);\n\n    function NORMALIZATION_0() external view returns (int256);\n\n    function NORMALIZATION_1() external view returns (int256);\n\n    function QUOTE_TOKEN_0() external view returns (address);\n\n    function QUOTE_TOKEN_0_DECIMALS() external view returns (uint256);\n\n    function QUOTE_TOKEN_1() external view returns (address);\n\n    function QUOTE_TOKEN_1_DECIMALS() external view returns (uint256);\n}\n"
      },
      "node_modules/@mean-finance/uniswap-v3-oracle/solidity/interfaces/IStaticOracle.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity >=0.7.6 <0.9.0;\n\nimport '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';\n\n/// @title Uniswap V3 Static Oracle\n/// @notice Oracle contract for calculating price quoting against Uniswap V3\ninterface IStaticOracle {\n  /// @notice Returns the address of the Uniswap V3 factory\n  /// @dev This value is assigned during deployment and cannot be changed\n  /// @return The address of the Uniswap V3 factory\n  function UNISWAP_V3_FACTORY() external view returns (IUniswapV3Factory);\n\n  /// @notice Returns how many observations are needed per minute in Uniswap V3 oracles, on the deployed chain\n  /// @dev This value is assigned during deployment and cannot be changed\n  /// @return Number of observation that are needed per minute\n  function CARDINALITY_PER_MINUTE() external view returns (uint8);\n\n  /// @notice Returns all supported fee tiers\n  /// @return The supported fee tiers\n  function supportedFeeTiers() external view returns (uint24[] memory);\n\n  /// @notice Returns whether a specific pair can be supported by the oracle\n  /// @dev The pair can be provided in tokenA/tokenB or tokenB/tokenA order\n  /// @return Whether the given pair can be supported by the oracle\n  function isPairSupported(address tokenA, address tokenB) external view returns (bool);\n\n  /// @notice Returns all existing pools for the given pair\n  /// @dev The pair can be provided in tokenA/tokenB or tokenB/tokenA order\n  /// @return All existing pools for the given pair\n  function getAllPoolsForPair(address tokenA, address tokenB) external view returns (address[] memory);\n\n  /// @notice Returns a quote, based on the given tokens and amount, by querying all of the pair's pools\n  /// @dev If some pools are not configured correctly for the given period, then they will be ignored\n  /// @dev Will revert if there are no pools available/configured for the pair and period combination\n  /// @param baseAmount Amount of token to be converted\n  /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\n  /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\n  /// @param period Number of seconds from which to calculate the TWAP\n  /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\n  /// @return queriedPools The pools that were queried to calculate the quote\n  function quoteAllAvailablePoolsWithTimePeriod(\n    uint128 baseAmount,\n    address baseToken,\n    address quoteToken,\n    uint32 period\n  ) external view returns (uint256 quoteAmount, address[] memory queriedPools);\n\n  /// @notice Returns a quote, based on the given tokens and amount, by querying only the specified fee tiers\n  /// @dev Will revert if the pair does not have a pool for one of the given fee tiers, or if one of the pools\n  /// is not prepared/configured correctly for the given period\n  /// @param baseAmount Amount of token to be converted\n  /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\n  /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\n  /// @param feeTiers The fee tiers to consider when calculating the quote\n  /// @param period Number of seconds from which to calculate the TWAP\n  /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\n  /// @return queriedPools The pools that were queried to calculate the quote\n  function quoteSpecificFeeTiersWithTimePeriod(\n    uint128 baseAmount,\n    address baseToken,\n    address quoteToken,\n    uint24[] calldata feeTiers,\n    uint32 period\n  ) external view returns (uint256 quoteAmount, address[] memory queriedPools);\n\n  /// @notice Returns a quote, based on the given tokens and amount, by querying only the specified pools\n  /// @dev Will revert if one of the pools is not prepared/configured correctly for the given period\n  /// @param baseAmount Amount of token to be converted\n  /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination\n  /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination\n  /// @param pools The pools to consider when calculating the quote\n  /// @param period Number of seconds from which to calculate the TWAP\n  /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken\n  function quoteSpecificPoolsWithTimePeriod(\n    uint128 baseAmount,\n    address baseToken,\n    address quoteToken,\n    address[] calldata pools,\n    uint32 period\n  ) external view returns (uint256 quoteAmount);\n\n  /// @notice Will initialize all existing pools for the given pair, so that they can be queried with the given period in the future\n  /// @dev Will revert if there are no pools available for the pair and period combination\n  /// @param tokenA One of the pair's tokens\n  /// @param tokenB The other of the pair's tokens\n  /// @param period The period that will be guaranteed when quoting\n  /// @return preparedPools The pools that were prepared\n  function prepareAllAvailablePoolsWithTimePeriod(\n    address tokenA,\n    address tokenB,\n    uint32 period\n  ) external returns (address[] memory preparedPools);\n\n  /// @notice Will initialize the pair's pools with the specified fee tiers, so that they can be queried with the given period in the future\n  /// @dev Will revert if the pair does not have a pool for a given fee tier\n  /// @param tokenA One of the pair's tokens\n  /// @param tokenB The other of the pair's tokens\n  /// @param feeTiers The fee tiers to consider when searching for the pair's pools\n  /// @param period The period that will be guaranteed when quoting\n  /// @return preparedPools The pools that were prepared\n  function prepareSpecificFeeTiersWithTimePeriod(\n    address tokenA,\n    address tokenB,\n    uint24[] calldata feeTiers,\n    uint32 period\n  ) external returns (address[] memory preparedPools);\n\n  /// @notice Will initialize all given pools, so that they can be queried with the given period in the future\n  /// @param pools The pools to initialize\n  /// @param period The period that will be guaranteed when quoting\n  function prepareSpecificPoolsWithTimePeriod(address[] calldata pools, uint32 period) external;\n\n  /// @notice Will increase observations for all existing pools for the given pair, so they start accruing information for twap calculations\n  /// @dev Will revert if there are no pools available for the pair and period combination\n  /// @param tokenA One of the pair's tokens\n  /// @param tokenB The other of the pair's tokens\n  /// @param cardinality The cardinality that will be guaranteed when quoting\n  /// @return preparedPools The pools that were prepared\n  function prepareAllAvailablePoolsWithCardinality(\n    address tokenA,\n    address tokenB,\n    uint16 cardinality\n  ) external returns (address[] memory preparedPools);\n\n  /// @notice Will increase the pair's pools with the specified fee tiers observations, so they start accruing information for twap calculations\n  /// @dev Will revert if the pair does not have a pool for a given fee tier\n  /// @param tokenA One of the pair's tokens\n  /// @param tokenB The other of the pair's tokens\n  /// @param feeTiers The fee tiers to consider when searching for the pair's pools\n  /// @param cardinality The cardinality that will be guaranteed when quoting\n  /// @return preparedPools The pools that were prepared\n  function prepareSpecificFeeTiersWithCardinality(\n    address tokenA,\n    address tokenB,\n    uint24[] calldata feeTiers,\n    uint16 cardinality\n  ) external returns (address[] memory preparedPools);\n\n  /// @notice Will increase all given pools observations, so they start accruing information for twap calculations\n  /// @param pools The pools to initialize\n  /// @param cardinality The cardinality that will be guaranteed when quoting\n  function prepareSpecificPoolsWithCardinality(address[] calldata pools, uint16 cardinality) external;\n\n  /// @notice Adds support for a new fee tier\n  /// @dev Will revert if the given tier is invalid, or already supported\n  /// @param feeTier The new fee tier to add\n  function addNewFeeTier(uint24 feeTier) external;\n}\n"
      },
      "src/contracts/utils/ERC165Storage.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Storage.sol)\npragma solidity ^0.8.0;\n\nimport { ERC165 } from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\n\n/**\n * @dev Storage based implementation of the {IERC165} interface.\n *\n * Contracts may inherit from this and call {_registerInterface} to declare\n * their support of an interface.\n */\nabstract contract ERC165Storage is ERC165 {\n    /**\n     * @dev Mapping of interface ids to whether or not it's supported.\n     */\n    mapping(bytes4 => bool) private _supportedInterfaces;\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return super.supportsInterface(interfaceId) || _supportedInterfaces[interfaceId];\n    }\n\n    /**\n     * @dev Registers the contract as an implementer of the interface defined by\n     * `interfaceId`. Support of the actual ERC165 interface is automatic and\n     * registering its interface id is not required.\n     *\n     * See {IERC165-supportsInterface}.\n     *\n     * Requirements:\n     *\n     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).\n     */\n    function _registerInterface(bytes4 interfaceId) internal virtual {\n        require(interfaceId != 0xffffffff, \"ERC165: invalid interface id\");\n        _supportedInterfaces[interfaceId] = true;\n    }\n}\n"
      },
      "src/contracts/interfaces/oracles/abstracts/IUniswapV3SingleTwapOracle.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.20;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ninterface IUniswapV3SingleTwapOracle is IERC165 {\n    event SetTwapDuration(uint256 oldTwapDuration, uint256 newTwapDuration);\n\n    function TWAP_PRECISION() external view returns (uint128);\n\n    function UNISWAP_V3_TWAP_BASE_TOKEN() external view returns (address);\n\n    function UNISWAP_V3_TWAP_QUOTE_TOKEN() external view returns (address);\n\n    function UNI_V3_PAIR_ADDRESS() external view returns (address);\n\n    function getUniswapV3Twap() external view returns (uint256 _twap);\n\n    function twapDuration() external view returns (uint32);\n\n    function setTwapDuration(uint32 _newTwapDuration) external;\n}\n"
      },
      "node_modules/@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n  function decimals() external view returns (uint8);\n\n  function description() external view returns (string memory);\n\n  function version() external view returns (uint256);\n\n  function getRoundData(uint80 _roundId)\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n\n  function latestRoundData()\n    external\n    view\n    returns (\n      uint80 roundId,\n      int256 answer,\n      uint256 startedAt,\n      uint256 updatedAt,\n      uint80 answeredInRound\n    );\n}\n"
      },
      "src/contracts/interfaces/oracles/abstracts/IChainlinkOracleWithMaxDelay.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.20;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ninterface IChainlinkOracleWithMaxDelay is IERC165 {\n    event SetMaximumOracleDelay(address oracle, uint256 oldMaxOracleDelay, uint256 newMaxOracleDelay);\n\n    function CHAINLINK_FEED_ADDRESS() external view returns (address);\n\n    function CHAINLINK_FEED_DECIMALS() external view returns (uint8);\n\n    function CHAINLINK_FEED_PRECISION() external view returns (uint256);\n\n    function getChainlinkPrice() external view returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth);\n\n    function maximumOracleDelay() external view returns (uint256);\n\n    function setMaximumOracleDelay(uint256 _newMaxOracleDelay) external;\n}\n"
      },
      "src/contracts/interfaces/oracles/abstracts/IEthUsdChainlinkOracleWithMaxDelay.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.8.20;\n\nimport { IERC165 } from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ninterface IEthUsdChainlinkOracleWithMaxDelay is IERC165 {\n    event SetMaximumEthUsdOracleDelay(uint256 oldMaxOracleDelay, uint256 newMaxOracleDelay);\n\n    function ETH_USD_CHAINLINK_FEED_ADDRESS() external view returns (address);\n\n    function ETH_USD_CHAINLINK_FEED_DECIMALS() external view returns (uint8);\n\n    function ETH_USD_CHAINLINK_FEED_PRECISION() external view returns (uint256);\n\n    function maximumEthUsdOracleDelay() external view returns (uint256);\n\n    function getEthUsdChainlinkPrice() external view returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth);\n\n    function setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) external;\n}\n"
      },
      "node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "node_modules/@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol": {
        "content": "// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title The interface for the Uniswap V3 Factory\n/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees\ninterface IUniswapV3Factory {\n    /// @notice Emitted when the owner of the factory is changed\n    /// @param oldOwner The owner before the owner was changed\n    /// @param newOwner The owner after the owner was changed\n    event OwnerChanged(address indexed oldOwner, address indexed newOwner);\n\n    /// @notice Emitted when a pool is created\n    /// @param token0 The first token of the pool by address sort order\n    /// @param token1 The second token of the pool by address sort order\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n    /// @param tickSpacing The minimum number of ticks between initialized ticks\n    /// @param pool The address of the created pool\n    event PoolCreated(\n        address indexed token0,\n        address indexed token1,\n        uint24 indexed fee,\n        int24 tickSpacing,\n        address pool\n    );\n\n    /// @notice Emitted when a new fee amount is enabled for pool creation via the factory\n    /// @param fee The enabled fee, denominated in hundredths of a bip\n    /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee\n    event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);\n\n    /// @notice Returns the current owner of the factory\n    /// @dev Can be changed by the current owner via setOwner\n    /// @return The address of the factory owner\n    function owner() external view returns (address);\n\n    /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled\n    /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context\n    /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee\n    /// @return The tick spacing\n    function feeAmountTickSpacing(uint24 fee) external view returns (int24);\n\n    /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist\n    /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order\n    /// @param tokenA The contract address of either token0 or token1\n    /// @param tokenB The contract address of the other token\n    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip\n    /// @return pool The pool address\n    function getPool(\n        address tokenA,\n        address tokenB,\n        uint24 fee\n    ) external view returns (address pool);\n\n    /// @notice Creates a pool for the given two tokens and fee\n    /// @param tokenA One of the two tokens in the desired pool\n    /// @param tokenB The other of the two tokens in the desired pool\n    /// @param fee The desired fee for the pool\n    /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved\n    /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments\n    /// are invalid.\n    /// @return pool The address of the newly created pool\n    function createPool(\n        address tokenA,\n        address tokenB,\n        uint24 fee\n    ) external returns (address pool);\n\n    /// @notice Updates the owner of the factory\n    /// @dev Must be called by the current owner\n    /// @param _owner The new owner of the factory\n    function setOwner(address _owner) external;\n\n    /// @notice Enables a fee amount with the given tickSpacing\n    /// @dev Fee amounts may never be removed once enabled\n    /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)\n    /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount\n    function enableFeeAmount(uint24 fee, int24 tickSpacing) external;\n}\n"
      },
      "node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=node_modules/ds-test/src/",
        "forge-std/=node_modules/forge-std/src/",
        "frax-std/=node_modules/frax-standard-solidity/src/",
        "script/=src/script/",
        "src/=src/",
        "test/=src/test/",
        "interfaces/=src/contracts/interfaces/",
        "arbitrum/=node_modules/@arbitrum/",
        "rlp/=node_modules/solidity-rlp/contracts/",
        "@solmate/=node_modules/@rari-capital/solmate/src/",
        "@arbitrum/=node_modules/@arbitrum/",
        "@chainlink/=node_modules/@chainlink/",
        "@eth-optimism/=node_modules/@eth-optimism/",
        "@mean-finance/=node_modules/@mean-finance/",
        "@offchainlabs/=node_modules/@offchainlabs/",
        "@openzeppelin/=node_modules/@openzeppelin/",
        "@rari-capital/=node_modules/@rari-capital/",
        "@uniswap/=node_modules/@uniswap/",
        "base64-sol/=node_modules/base64-sol/",
        "frax-standard-solidity/=node_modules/frax-standard-solidity/",
        "hardhat/=node_modules/hardhat/",
        "prb-math/=node_modules/prb-math/",
        "solidity-bytes-utils/=node_modules/solidity-bytes-utils/",
        "solidity-rlp/=node_modules/solidity-rlp/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 1000000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "none",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "shanghai",
      "viaIR": false,
      "libraries": {}
    }
  }}