{"file_path":"lib/mento-core/contracts/oracles/OracleAdapter.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.24;\n\nimport { IOracleAdapter } from \"../interfaces/IOracleAdapter.sol\";\nimport { IBreakerBox } from \"../interfaces/IBreakerBox.sol\";\nimport { ISortedOracles } from \"../interfaces/ISortedOracles.sol\";\nimport { IMarketHoursBreaker } from \"../interfaces/IMarketHoursBreaker.sol\";\nimport { AggregatorV3Interface } from \"foundry-chainlink-toolkit/src/interfaces/feeds/AggregatorV3Interface.sol\";\n\nimport { OwnableUpgradeable } from \"openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol\";\n\ncontract OracleAdapter is IOracleAdapter, OwnableUpgradeable {\n  /* ============================================================ */\n  /* ======================== Constants ========================= */\n  /* ============================================================ */\n\n  uint256 public constant TRADING_MODE_BIDIRECTIONAL = 0;\n\n  // keccak256(abi.encode(uint256(keccak256(\"mento.storage.OracleAdapter\")) - 1)) & ~bytes32(uint256(0xff))\n  bytes32 private constant _ORACLE_ADAPTER_STORAGE_LOCATION =\n    0x04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c400;\n\n  /* ============================================================ */\n  /* ======================== Constructor ======================= */\n  /* ============================================================ */\n\n  /**\n   * @notice Contract constructor\n   * @param disable Boolean to disable initializers for implementation contract\n   */\n  constructor(bool disable) {\n    if (disable) {\n      _disableInitializers();\n    }\n  }\n\n  /* ============================================================ */\n  /* ==================== Initialization ======================== */\n  /* ============================================================ */\n\n  /// @inheritdoc IOracleAdapter\n  function initialize(\n    address _sortedOracles,\n    address _breakerBox,\n    address _marketHoursBreaker,\n    address _l2SequencerUptimeFeed,\n    address _initialOwner\n  ) external initializer {\n    __Ownable_init();\n\n    setSortedOracles(_sortedOracles);\n    setBreakerBox(_breakerBox);\n    setMarketHoursBreaker(_marketHoursBreaker);\n    setL2SequencerUptimeFeed(_l2SequencerUptimeFeed);\n\n    transferOwnership(_initialOwner);\n  }\n\n  /* ============================================================ */\n  /* ==================== Admin Functions ======================= */\n  /* ============================================================ */\n\n  /// @inheritdoc IOracleAdapter\n  function setSortedOracles(address _sortedOracles) public onlyOwner {\n    if (_sortedOracles == address(0)) revert ZeroAddress();\n\n    OracleAdapterStorage storage $ = _getStorage();\n    address oldSortedOracles = address($.sortedOracles);\n    $.sortedOracles = ISortedOracles(_sortedOracles);\n\n    emit SortedOraclesUpdated(oldSortedOracles, _sortedOracles);\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function setBreakerBox(address _breakerBox) public onlyOwner {\n    if (_breakerBox == address(0)) revert ZeroAddress();\n\n    OracleAdapterStorage storage $ = _getStorage();\n    address oldBreakerBox = address($.breakerBox);\n    $.breakerBox = IBreakerBox(_breakerBox);\n\n    emit BreakerBoxUpdated(oldBreakerBox, _breakerBox);\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function setMarketHoursBreaker(address _marketHoursBreaker) public onlyOwner {\n    if (_marketHoursBreaker == address(0)) revert ZeroAddress();\n\n    OracleAdapterStorage storage $ = _getStorage();\n    address oldMarketHoursBreaker = address($.marketHoursBreaker);\n    $.marketHoursBreaker = IMarketHoursBreaker(_marketHoursBreaker);\n\n    emit MarketHoursBreakerUpdated(oldMarketHoursBreaker, _marketHoursBreaker);\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function setL2SequencerUptimeFeed(address _l2SequencerUptimeFeed) public onlyOwner {\n    OracleAdapterStorage storage $ = _getStorage();\n\n    address oldL2SequencerUptimeFeed = address($.l2SequencerUptimeFeed);\n    $.l2SequencerUptimeFeed = AggregatorV3Interface(_l2SequencerUptimeFeed);\n\n    emit L2SequencerUptimeFeedUpdated(oldL2SequencerUptimeFeed, _l2SequencerUptimeFeed);\n  }\n\n  /* ============================================================ */\n  /* ===================== View Functions ======================= */\n  /* ============================================================ */\n\n  function sortedOracles() external view returns (ISortedOracles) {\n    OracleAdapterStorage storage $ = _getStorage();\n    return $.sortedOracles;\n  }\n\n  function breakerBox() external view returns (IBreakerBox) {\n    OracleAdapterStorage storage $ = _getStorage();\n    return $.breakerBox;\n  }\n\n  function marketHoursBreaker() external view returns (IMarketHoursBreaker) {\n    OracleAdapterStorage storage $ = _getStorage();\n    return $.marketHoursBreaker;\n  }\n\n  function l2SequencerUptimeFeed() external view returns (AggregatorV3Interface) {\n    OracleAdapterStorage storage $ = _getStorage();\n    return $.l2SequencerUptimeFeed;\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function isFXMarketOpen() external view returns (bool) {\n    return _isFXMarketOpen();\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function getTradingMode(address rateFeedID) external view returns (uint8) {\n    return _getTradingMode(rateFeedID);\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function getRate(address rateFeedID) external view returns (RateInfo memory) {\n    // slither-disable-next-line uninitialized-local\n    RateInfo memory rateInfo;\n\n    (uint256 numerator, uint256 denominator) = _getOracleRate(rateFeedID);\n\n    rateInfo.numerator = numerator;\n    rateInfo.denominator = denominator;\n    rateInfo.tradingMode = _getTradingMode(rateFeedID);\n    rateInfo.isRecent = _hasRecentRate(rateFeedID);\n    rateInfo.isFXMarketOpen = _isFXMarketOpen();\n\n    return rateInfo;\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function getRateIfValid(address rateFeedID) external view returns (uint256 numerator, uint256 denominator) {\n    if (_getTradingMode(rateFeedID) != TRADING_MODE_BIDIRECTIONAL) revert TradingSuspended();\n    if (!_hasRecentRate(rateFeedID)) revert NoRecentRate();\n\n    return _getOracleRate(rateFeedID);\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function getFXRateIfValid(address rateFeedID) external view returns (uint256 numerator, uint256 denominator) {\n    if (!_isFXMarketOpen()) revert FXMarketClosed();\n    if (_getTradingMode(rateFeedID) != TRADING_MODE_BIDIRECTIONAL) revert TradingSuspended();\n    if (!_hasRecentRate(rateFeedID)) revert NoRecentRate();\n\n    return _getOracleRate(rateFeedID);\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function hasRecentRate(address rateFeedID) external view returns (bool) {\n    return _hasRecentRate(rateFeedID);\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function ensureRateValid(address rateFeedID) external view {\n    if (_getTradingMode(rateFeedID) != TRADING_MODE_BIDIRECTIONAL) revert TradingSuspended();\n    if (!_hasRecentRate(rateFeedID)) revert NoRecentRate();\n    _getOracleRate(rateFeedID);\n  }\n\n  /// @inheritdoc IOracleAdapter\n  function isL2SequencerUp(uint256 since) external view returns (bool) {\n    OracleAdapterStorage storage $ = _getStorage();\n\n    if (address($.l2SequencerUptimeFeed) == address(0)) return true;\n\n    // slither-disable-next-line unused-return\n    (, int256 answer, , uint256 startedAt, ) = $.l2SequencerUptimeFeed.latestRoundData();\n    return answer == 0 && block.timestamp - startedAt > since;\n  }\n\n  /* ============================================================ */\n  /* ==================== Private Functions ===================== */\n  /* ============================================================ */\n\n  function _isFXMarketOpen() private view returns (bool) {\n    OracleAdapterStorage storage $ = _getStorage();\n\n    return $.marketHoursBreaker.isFXMarketOpen(block.timestamp);\n  }\n\n  function _getTradingMode(address rateFeedID) private view returns (uint8) {\n    OracleAdapterStorage storage $ = _getStorage();\n\n    return $.breakerBox.getRateFeedTradingMode(rateFeedID);\n  }\n\n  function _getOracleRate(address rateFeedID) private view returns (uint256 numerator, uint256 denominator) {\n    OracleAdapterStorage storage $ = _getStorage();\n\n    (numerator, denominator) = $.sortedOracles.medianRate(rateFeedID);\n    assert(denominator == 1e24); // denominator from sorted oracles should always be 1e24\n\n    numerator = numerator / 1e6;\n    denominator = denominator / 1e6;\n\n    if (numerator == 0 || denominator == 0) revert InvalidRate();\n  }\n\n  function _hasRecentRate(address rateFeedID) private view returns (bool) {\n    OracleAdapterStorage storage $ = _getStorage();\n\n    uint256 reportExpiry = $.sortedOracles.getTokenReportExpirySeconds(rateFeedID);\n    uint256 reportTs = $.sortedOracles.medianTimestamp(rateFeedID);\n\n    return reportTs >= block.timestamp - reportExpiry;\n  }\n\n  /**\n   * @notice Returns the pointer to the OracleAdapterStorage struct.\n   * @return $ The pointer to the OracleAdapterStorage struct\n   */\n  function _getStorage() private pure returns (OracleAdapterStorage storage $) {\n    // solhint-disable-next-line no-inline-assembly\n    assembly {\n      $.slot := _ORACLE_ADAPTER_STORAGE_LOCATION\n    }\n  }\n}\n","deployed_bytecode":"0x608060405234801561000f575f80fd5b5060043610610132575f3560e01c80635438a8c4116100b4578063ba76a68011610079578063ba76a680146102fe578063cd8e99941461032e578063d12668cd14610341578063d85ae71214610354578063f2fde38b14610367578063f414c5e41461037a575f80fd5b80635438a8c41461027b5780635ca0c578146102a0578063715018a6146102b55780638da5cb5b146102bd5780639b0fa8aa146102ce575f80fd5b80631ceb4e14116100fa5780631ceb4e14146101bf57806337cef791146101e75780634afb215e146102425780634dbd9eb1146102555780634e6e0de214610268575f80fd5b8063040bbd3514610136578063099b6c391461014b578063132e8aa71461015e5780631459457a1461019457806315d89632146101a7575b5f80fd5b610149610144366004610eb4565b6103aa565b005b610149610159366004610eb4565b61045a565b5f805160206110b4833981519152546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6101496101a2366004610ecd565b61050a565b6101af61064c565b604051901515815260200161018b565b6101d26101cd366004610eb4565b61065a565b6040805192835260208301919091520161018b565b6101fa6101f5366004610eb4565b6106e4565b60405161018b91905f60a082019050825182526020830151602083015260ff604084015116604083015260608301511515606083015260808301511515608083015292915050565b610149610250366004610eb4565b61078b565b6101d2610263366004610eb4565b610817565b6101af610276366004610eb4565b610823565b61028e610289366004610eb4565b610833565b60405160ff909116815260200161018b565b6102a75f81565b60405190815260200161018b565b61014961083d565b6033546001600160a01b0316610177565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c402546001600160a01b0316610177565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c403546001600160a01b0316610177565b6101af61033c366004610f2e565b610850565b61014961034f366004610eb4565b610938565b610149610362366004610eb4565b6109c1565b610149610375366004610eb4565b610a20565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c401546001600160a01b0316610177565b6103b2610a99565b6001600160a01b0381166103d95760405163d92e233d60e01b815260040160405180910390fd5b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c40180546001600160a01b031981166001600160a01b038481169182179093556040515f805160206110b4833981519152939092169182907f8d79c72d13fc06d00ec2569230bccf1fad57a1c252cba5ec5c2be3db3f234de9905f90a3505050565b610462610a99565b6001600160a01b0381166104895760405163d92e233d60e01b815260040160405180910390fd5b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c40280546001600160a01b031981166001600160a01b038481169182179093556040515f805160206110b4833981519152939092169182907f829e18c1478628aa3f35da681ccd84c97c877b93325a843d824b77db2b803079905f90a3505050565b5f54610100900460ff161580801561052857505f54600160ff909116105b806105415750303b15801561054157505f5460ff166001145b6105a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff1916600117905580156105ca575f805461ff0019166101001790555b6105d2610af3565b6105db8661078b565b6105e4856103aa565b6105ed8461045a565b6105f683610938565b6105ff82610a20565b8015610644575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b5f610655610b21565b905090565b5f80610664610b21565b610681576040516352038a1d60e11b815260040160405180910390fd5b5f61068b84610ba4565b60ff16146106ac57604051632561861160e11b815260040160405180910390fd5b6106b583610c2b565b6106d25760405163eb0d3e8160e01b815260040160405180910390fd5b6106db83610d31565b91509150915091565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091526040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f8061074385610d31565b81855260208501819052909250905061075b85610ba4565b60ff16604084015261076c85610c2b565b1515606084015261077b610b21565b1515608084015250909392505050565b610793610a99565b6001600160a01b0381166107ba5760405163d92e233d60e01b815260040160405180910390fd5b5f805160206110b483398151915280546001600160a01b031981166001600160a01b03848116918217845560405192169182907f747bac427be89756b0d4363ad9101c19437d443b8d425853d6a17da86adee5aa905f90a3505050565b5f805f61068b84610ba4565b5f61082d82610c2b565b92915050565b5f61082d82610ba4565b610845610a99565b61084e5f610e19565b565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c403545f905f805160206110b4833981519152906001600160a01b03166108995750600192915050565b5f80826003015f9054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156108ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109119190610f5e565b50935050925050815f14801561092f57508461092d8242610f9e565b115b95945050505050565b610940610a99565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c40380546001600160a01b031981166001600160a01b038481169182179093556040515f805160206110b4833981519152939092169182907fd282ea00fe305eed80a577ba9b3ff88e1d6a14f0bdd77a6ef690071e62d6a165905f90a3505050565b5f6109cb82610ba4565b60ff16146109ec57604051632561861160e11b815260040160405180910390fd5b6109f581610c2b565b610a125760405163eb0d3e8160e01b815260040160405180910390fd5b610a1b81610d31565b505050565b610a28610a99565b6001600160a01b038116610a8d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105a0565b610a9681610e19565b50565b6033546001600160a01b0316331461084e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105a0565b5f54610100900460ff16610b195760405162461bcd60e51b81526004016105a090610fbd565b61084e610e6a565b5f805f805160206110b4833981519152600281015460405163d9c220b360e01b81524260048201529192506001600160a01b03169063d9c220b390602401602060405180830381865afa158015610b7a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9e9190611008565b91505090565b5f805f805160206110b4833981519152600181015460405163060582ed60e51b81526001600160a01b03868116600483015292935091169063c0b05da090602401602060405180830381865afa158015610c00573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c249190611027565b9392505050565b5f805f805160206110b48339815191528054604051636deb679960e01b81526001600160a01b0386811660048301529293505f9290911690636deb679990602401602060405180830381865afa158015610c87573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cab9190611047565b82546040516301c6d23f60e21b81526001600160a01b0387811660048301529293505f929091169063071b48fc90602401602060405180830381865afa158015610cf7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1b9190611047565b9050610d278242610f9e565b1115949350505050565b5f80805f805160206110b48339815191528054604051630ef90e1b60e41b81526001600160a01b03878116600483015292935091169063ef90e1b0906024016040805180830381865afa158015610d8a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dae919061105e565b909350915069d3c21bcecceda10000008214610dcc57610dcc611080565b610dd9620f424084611094565b9250610de8620f424083611094565b9150821580610df5575081155b15610e1357604051636a43f8d160e01b815260040160405180910390fd5b50915091565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff16610e905760405162461bcd60e51b81526004016105a090610fbd565b61084e33610e19565b80356001600160a01b0381168114610eaf575f80fd5b919050565b5f60208284031215610ec4575f80fd5b610c2482610e99565b5f805f805f60a08688031215610ee1575f80fd5b610eea86610e99565b9450610ef860208701610e99565b9350610f0660408701610e99565b9250610f1460608701610e99565b9150610f2260808701610e99565b90509295509295909350565b5f60208284031215610f3e575f80fd5b5035919050565b805169ffffffffffffffffffff81168114610eaf575f80fd5b5f805f805f60a08688031215610f72575f80fd5b610f7b86610f45565b9450602086015193506040860151925060608601519150610f2260808701610f45565b8181038181111561082d57634e487b7160e01b5f52601160045260245ffd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f60208284031215611018575f80fd5b81518015158114610c24575f80fd5b5f60208284031215611037575f80fd5b815160ff81168114610c24575f80fd5b5f60208284031215611057575f80fd5b5051919050565b5f806040838503121561106f575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52600160045260245ffd5b5f826110ae57634e487b7160e01b5f52601260045260245ffd5b50049056fe04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c400a26469706673582212201be710ea4adf3c4e1cf8b14ddb5c3ca37c8dba7d1e0bb6c91a49109a1479af8d64736f6c63430008180033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":200},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["src/=src/","lib/mento-core/lib/bold/:openzeppelin-contracts/=lib/mento-core/lib/bold/contracts/lib/openzeppelin-contracts/","openzeppelin-contracts/=lib/mento-core/lib/openzeppelin-contracts-next/","safe-smart-account/=lib/treb-sol/lib/safe-utils/lib/safe-smart-account/contracts/","mento-core/=lib/mento-core/contracts/","@celo/=lib/mento-core/node_modules/@celo/contracts/","@chainlink/contracts/=lib/mento-core/lib/foundry-chainlink-toolkit/lib/chainlink-brownie-contracts/contracts/src/","@ds/=lib/mento-router/lib/multicall/lib/ds-test/src/","@openzeppelin/=lib/mento-core/lib/foundry-chainlink-toolkit/lib/openzeppelin-contracts/","@prb/test/=lib/mento-core/lib/prb-math/lib/prb-test/src/","@std/=lib/mento-router/lib/multicall/lib/forge-std/src/","BokkyPooBahsDateTimeLibrary/=lib/mento-core/lib/BokkyPooBahsDateTimeLibrary/","Solady/=lib/mento-core/lib/bold/contracts/lib/Solady/src/","V2-gov/=lib/mento-core/lib/bold/contracts/lib/V2-gov/","bold/=lib/mento-core/lib/bold/contracts/","celo/=lib/mento-core/node_modules/@celo/","chainlink-brownie-contracts/=lib/mento-core/lib/foundry-chainlink-toolkit/lib/chainlink-brownie-contracts/contracts/src/v0.6/vendor/@arbitrum/nitro-contracts/src/","chimera/=lib/mento-core/lib/bold/contracts/lib/V2-gov/lib/chimera/src/","contracts/=lib/mento-core/contracts/","createx-forge/=lib/treb-sol/lib/createx-forge/","ds-test/=lib/mento-router/lib/multicall/lib/ds-test/src/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","foundry-chainlink-toolkit/=lib/mento-core/lib/foundry-chainlink-toolkit/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","mento-router/=lib/mento-router/","mento-std/=lib/mento-std/src/","multicall/=lib/mento-router/lib/multicall/src/","openzeppelin-contracts-next/=lib/mento-core/lib/openzeppelin-contracts-next/","openzeppelin-contracts-upgradeable/=lib/mento-core/lib/openzeppelin-contracts-upgradeable/","openzeppelin-solidity/=lib/mento-core/lib/openzeppelin-contracts/","openzeppelin/=lib/mento-core/lib/openzeppelin-contracts/","prb-math/=lib/mento-core/lib/prb-math/src/","prb-test/=lib/mento-core/lib/prb-math/lib/prb-test/src/","prb/math/=lib/mento-core/lib/prb-math/src/","safe-contracts/=lib/mento-core/lib/safe-contracts/","safe-utils/=lib/treb-sol/lib/safe-utils/src/","solidity-http/=lib/treb-sol/lib/safe-utils/lib/solidity-http/src/","solidity-stringutils/=lib/treb-sol/lib/safe-utils/lib/solidity-stringutils/","test/=lib/mento-core/test/","treb-sol/=lib/treb-sol/","lib/bold/:openzeppelin-contracts/=lib/mento-core/lib/bold/contracts/lib/openzeppelin-contracts/"],"viaIR":false},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":[["true",{"internalType":"bool","name":"disable","type":"bool"}]],"compiler_version":"v0.8.24+commit.e11b9ed9","is_verified_via_verifier_alliance":false,"verified_at":"2026-06-18T22:38:25.480224Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x608060405234801561000f575f80fd5b5060405161123b38038061123b83398101604081905261002e916100ff565b801561003c5761003c610042565b50610125565b5f54610100900460ff16156100ad5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811610156100fd575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b5f6020828403121561010f575f80fd5b8151801515811461011e575f80fd5b9392505050565b611109806101325f395ff3fe608060405234801561000f575f80fd5b5060043610610132575f3560e01c80635438a8c4116100b4578063ba76a68011610079578063ba76a680146102fe578063cd8e99941461032e578063d12668cd14610341578063d85ae71214610354578063f2fde38b14610367578063f414c5e41461037a575f80fd5b80635438a8c41461027b5780635ca0c578146102a0578063715018a6146102b55780638da5cb5b146102bd5780639b0fa8aa146102ce575f80fd5b80631ceb4e14116100fa5780631ceb4e14146101bf57806337cef791146101e75780634afb215e146102425780634dbd9eb1146102555780634e6e0de214610268575f80fd5b8063040bbd3514610136578063099b6c391461014b578063132e8aa71461015e5780631459457a1461019457806315d89632146101a7575b5f80fd5b610149610144366004610eb4565b6103aa565b005b610149610159366004610eb4565b61045a565b5f805160206110b4833981519152546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b6101496101a2366004610ecd565b61050a565b6101af61064c565b604051901515815260200161018b565b6101d26101cd366004610eb4565b61065a565b6040805192835260208301919091520161018b565b6101fa6101f5366004610eb4565b6106e4565b60405161018b91905f60a082019050825182526020830151602083015260ff604084015116604083015260608301511515606083015260808301511515608083015292915050565b610149610250366004610eb4565b61078b565b6101d2610263366004610eb4565b610817565b6101af610276366004610eb4565b610823565b61028e610289366004610eb4565b610833565b60405160ff909116815260200161018b565b6102a75f81565b60405190815260200161018b565b61014961083d565b6033546001600160a01b0316610177565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c402546001600160a01b0316610177565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c403546001600160a01b0316610177565b6101af61033c366004610f2e565b610850565b61014961034f366004610eb4565b610938565b610149610362366004610eb4565b6109c1565b610149610375366004610eb4565b610a20565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c401546001600160a01b0316610177565b6103b2610a99565b6001600160a01b0381166103d95760405163d92e233d60e01b815260040160405180910390fd5b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c40180546001600160a01b031981166001600160a01b038481169182179093556040515f805160206110b4833981519152939092169182907f8d79c72d13fc06d00ec2569230bccf1fad57a1c252cba5ec5c2be3db3f234de9905f90a3505050565b610462610a99565b6001600160a01b0381166104895760405163d92e233d60e01b815260040160405180910390fd5b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c40280546001600160a01b031981166001600160a01b038481169182179093556040515f805160206110b4833981519152939092169182907f829e18c1478628aa3f35da681ccd84c97c877b93325a843d824b77db2b803079905f90a3505050565b5f54610100900460ff161580801561052857505f54600160ff909116105b806105415750303b15801561054157505f5460ff166001145b6105a95760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff1916600117905580156105ca575f805461ff0019166101001790555b6105d2610af3565b6105db8661078b565b6105e4856103aa565b6105ed8461045a565b6105f683610938565b6105ff82610a20565b8015610644575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b5f610655610b21565b905090565b5f80610664610b21565b610681576040516352038a1d60e11b815260040160405180910390fd5b5f61068b84610ba4565b60ff16146106ac57604051632561861160e11b815260040160405180910390fd5b6106b583610c2b565b6106d25760405163eb0d3e8160e01b815260040160405180910390fd5b6106db83610d31565b91509150915091565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101919091526040805160a0810182525f808252602082018190529181018290526060810182905260808101919091525f8061074385610d31565b81855260208501819052909250905061075b85610ba4565b60ff16604084015261076c85610c2b565b1515606084015261077b610b21565b1515608084015250909392505050565b610793610a99565b6001600160a01b0381166107ba5760405163d92e233d60e01b815260040160405180910390fd5b5f805160206110b483398151915280546001600160a01b031981166001600160a01b03848116918217845560405192169182907f747bac427be89756b0d4363ad9101c19437d443b8d425853d6a17da86adee5aa905f90a3505050565b5f805f61068b84610ba4565b5f61082d82610c2b565b92915050565b5f61082d82610ba4565b610845610a99565b61084e5f610e19565b565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c403545f905f805160206110b4833981519152906001600160a01b03166108995750600192915050565b5f80826003015f9054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156108ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109119190610f5e565b50935050925050815f14801561092f57508461092d8242610f9e565b115b95945050505050565b610940610a99565b7f04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c40380546001600160a01b031981166001600160a01b038481169182179093556040515f805160206110b4833981519152939092169182907fd282ea00fe305eed80a577ba9b3ff88e1d6a14f0bdd77a6ef690071e62d6a165905f90a3505050565b5f6109cb82610ba4565b60ff16146109ec57604051632561861160e11b815260040160405180910390fd5b6109f581610c2b565b610a125760405163eb0d3e8160e01b815260040160405180910390fd5b610a1b81610d31565b505050565b610a28610a99565b6001600160a01b038116610a8d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016105a0565b610a9681610e19565b50565b6033546001600160a01b0316331461084e5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105a0565b5f54610100900460ff16610b195760405162461bcd60e51b81526004016105a090610fbd565b61084e610e6a565b5f805f805160206110b4833981519152600281015460405163d9c220b360e01b81524260048201529192506001600160a01b03169063d9c220b390602401602060405180830381865afa158015610b7a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9e9190611008565b91505090565b5f805f805160206110b4833981519152600181015460405163060582ed60e51b81526001600160a01b03868116600483015292935091169063c0b05da090602401602060405180830381865afa158015610c00573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c249190611027565b9392505050565b5f805f805160206110b48339815191528054604051636deb679960e01b81526001600160a01b0386811660048301529293505f9290911690636deb679990602401602060405180830381865afa158015610c87573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cab9190611047565b82546040516301c6d23f60e21b81526001600160a01b0387811660048301529293505f929091169063071b48fc90602401602060405180830381865afa158015610cf7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d1b9190611047565b9050610d278242610f9e565b1115949350505050565b5f80805f805160206110b48339815191528054604051630ef90e1b60e41b81526001600160a01b03878116600483015292935091169063ef90e1b0906024016040805180830381865afa158015610d8a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610dae919061105e565b909350915069d3c21bcecceda10000008214610dcc57610dcc611080565b610dd9620f424084611094565b9250610de8620f424083611094565b9150821580610df5575081155b15610e1357604051636a43f8d160e01b815260040160405180910390fd5b50915091565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f54610100900460ff16610e905760405162461bcd60e51b81526004016105a090610fbd565b61084e33610e19565b80356001600160a01b0381168114610eaf575f80fd5b919050565b5f60208284031215610ec4575f80fd5b610c2482610e99565b5f805f805f60a08688031215610ee1575f80fd5b610eea86610e99565b9450610ef860208701610e99565b9350610f0660408701610e99565b9250610f1460608701610e99565b9150610f2260808701610e99565b90509295509295909350565b5f60208284031215610f3e575f80fd5b5035919050565b805169ffffffffffffffffffff81168114610eaf575f80fd5b5f805f805f60a08688031215610f72575f80fd5b610f7b86610f45565b9450602086015193506040860151925060608601519150610f2260808701610f45565b8181038181111561082d57634e487b7160e01b5f52601160045260245ffd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f60208284031215611018575f80fd5b81518015158114610c24575f80fd5b5f60208284031215611037575f80fd5b815160ff81168114610c24575f80fd5b5f60208284031215611057575f80fd5b5051919050565b5f806040838503121561106f575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52600160045260245ffd5b5f826110ae57634e487b7160e01b5f52601260045260245ffd5b50049056fe04e664c42d77958a8a4a4091eaa097623a29a223ec89dc71155113e263f9c400a26469706673582212201be710ea4adf3c4e1cf8b14ddb5c3ca37c8dba7d1e0bb6c91a49109a1479af8d64736f6c634300081800330000000000000000000000000000000000000000000000000000000000000001","name":"OracleAdapter","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"lib/mento-core/contracts/interfaces/IBreakerBox.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity >0.5.13 <0.9;\npragma experimental ABIEncoderV2;\n\nimport { ISortedOracles } from \"./ISortedOracles.sol\";\n\n/**\n * @title Breaker Box Interface\n * @notice Defines the basic interface for the Breaker Box\n */\ninterface IBreakerBox {\n  /**\n   * @dev Used to keep track of the status of a breaker for a specific rate feed.\n   *\n   * - TradingMode: Represents the trading mode the breaker is in for a rate feed.\n   *                This uses a bitmask approach, meaning each bit represents a\n   *                different trading mode. The final trading mode of the rate feed\n   *                is obtained by applying a logical OR operation to the TradingMode\n   *                of all breakers associated with that rate feed. This allows multiple\n   *                breakers to contribute to the final trading mode simultaneously.\n   *                Possible values:\n   *                0: bidirectional trading.\n   *                1: inflow only.\n   *                2: outflow only.\n   *                3: trading halted.\n   *\n   * - LastUpdatedTime: Records the last time the breaker status was updated. This is\n   *                    used to manage cooldown periods before the breaker can be reset.\n   *\n   * - Enabled:     Indicates whether the breaker is enabled for the associated rate feed.\n   */\n  struct BreakerStatus {\n    uint8 tradingMode;\n    uint64 lastUpdatedTime;\n    bool enabled;\n  }\n\n  /**\n   * @notice Emitted when a new breaker is added to the breaker box.\n   * @param breaker The address of the breaker.\n   */\n  event BreakerAdded(address indexed breaker);\n\n  /**\n   * @notice Emitted when a breaker is removed from the breaker box.\n   * @param breaker The address of the breaker.\n   */\n  event BreakerRemoved(address indexed breaker);\n\n  /**\n   * @notice Emitted when a breaker is tripped by a rate feed.\n   * @param breaker The address of the breaker.\n   * @param rateFeedID The address of the rate feed.\n   */\n  event BreakerTripped(address indexed breaker, address indexed rateFeedID);\n\n  /**\n   * @notice Emitted when a new rate feed is added to the breaker box.\n   * @param rateFeedID The address of the rate feed.\n   */\n  event RateFeedAdded(address indexed rateFeedID);\n\n  /**\n   * @notice Emitted when dependencies for a rate feed are set.\n   * @param rateFeedID The address of the rate feed.\n   * @param dependencies The addresses of the dependendent rate feeds.\n   */\n  event RateFeedDependenciesSet(address indexed rateFeedID, address[] indexed dependencies);\n\n  /**\n   * @notice Emitted when a rate feed is removed from the breaker box.\n   * @param rateFeedID The address of the rate feed.\n   */\n  event RateFeedRemoved(address indexed rateFeedID);\n\n  /**\n   * @notice Emitted when the trading mode for a rate feed is updated\n   * @param rateFeedID The address of the rate feed.\n   * @param tradingMode The new trading mode.\n   */\n  event TradingModeUpdated(address indexed rateFeedID, uint256 tradingMode);\n\n  /**\n   * @notice Emitted after a reset attempt is successful.\n   * @param rateFeedID The address of the rate feed.\n   * @param breaker The address of the breaker.\n   */\n  event ResetSuccessful(address indexed rateFeedID, address indexed breaker);\n\n  /**\n   * @notice  Emitted after a reset attempt fails when the\n   *          rate feed fails the breakers reset criteria.\n   * @param rateFeedID The address of the rate feed.\n   * @param breaker The address of the breaker.\n   */\n  event ResetAttemptCriteriaFail(address indexed rateFeedID, address indexed breaker);\n\n  /**\n   * @notice Emitted after a reset attempt fails when cooldown time has not elapsed.\n   * @param rateFeedID The address of the rate feed.\n   * @param breaker The address of the breaker.\n   */\n  event ResetAttemptNotCool(address indexed rateFeedID, address indexed breaker);\n\n  /**\n   * @notice Emitted when the sortedOracles address is updated.\n   * @param newSortedOracles The address of the new sortedOracles.\n   */\n  event SortedOraclesUpdated(address indexed newSortedOracles);\n\n  /**\n   * @notice Emitted when the breaker is enabled or disabled for a rate feed.\n   * @param breaker The address of the breaker.\n   * @param rateFeedID The address of the rate feed.\n   * @param status Indicating the status.\n   */\n  event BreakerStatusUpdated(address breaker, address rateFeedID, bool status);\n\n  /**\n   * @notice Retrives an array of all breaker addresses.\n   */\n  function getBreakers() external view returns (address[] memory);\n\n  /**\n   * @notice Checks if a breaker with the specified address has been added to the breaker box.\n   * @param breaker The address of the breaker to check;\n   * @return A bool indicating whether or not the breaker has been added.\n   */\n  function isBreaker(address breaker) external view returns (bool);\n\n  /**\n   * @notice Checks breakers for the rateFeedID and sets correct trading mode\n   * if any breakers are tripped or need to be reset.\n   * @param rateFeedID The address of the rate feed to run checks for.\n   */\n  function checkAndSetBreakers(address rateFeedID) external;\n\n  /**\n   * @notice Gets the trading mode for the specified rateFeedID.\n   * @param rateFeedID The address of the rate feed to retrieve the trading mode for.\n   */\n  function getRateFeedTradingMode(address rateFeedID) external view returns (uint8 tradingMode);\n\n  /**\n   * @notice Adds a breaker to the end of the list of breakers & the breakerTradingMode mapping.\n   * @param breaker The address of the breaker to be added.\n   * @param tradingMode The trading mode of the breaker to be added.\n   */\n  function addBreaker(address breaker, uint8 tradingMode) external;\n\n  /**\n   * @notice Removes the specified breaker from the list of breakers\n   *         and resets breakerTradingMode mapping + BreakerStatus.\n   * @param breaker The address of the breaker to be removed.\n   */\n  function removeBreaker(address breaker) external;\n\n  /**\n   * @notice Enables or disables a breaker for the specified rate feed.\n   * @param breakerAddress The address of the breaker.\n   * @param rateFeedID The address of the rateFeed to be toggled.\n   * @param enable Boolean indicating whether the breaker should be\n   *               enabled or disabled for the given rateFeed.\n   */\n  function toggleBreaker(address breakerAddress, address rateFeedID, bool enable) external;\n\n  /**\n   * @notice Adds a rateFeedID to the mapping of monitored rateFeedIDs.\n   * @param rateFeedID The address of the rateFeed to be added.\n   */\n  function addRateFeed(address rateFeedID) external;\n\n  /**\n   * @notice Adds the specified rateFeedIDs to the mapping of monitored rateFeedIDs.\n   * @param newRateFeedIDs The array of rateFeed addresses to be added.\n   */\n  function addRateFeeds(address[] calldata newRateFeedIDs) external;\n\n  /**\n   * @notice Sets dependent rate feeds for a given rate feed.\n   * @param rateFeedID The address of the rate feed.\n   * @param dependencies The array of dependent rate feeds.\n   */\n  function setRateFeedDependencies(address rateFeedID, address[] calldata dependencies) external;\n\n  /**\n   * @notice Removes a rateFeed from the mapping of monitored rateFeeds\n   *         and resets all the BreakerStatus entries for that rateFeed.\n   * @param rateFeedID The address of the rateFeed to be removed.\n   */\n  function removeRateFeed(address rateFeedID) external;\n\n  /**\n   * @notice Sets the trading mode for the specified rateFeed.\n   * @param rateFeedID The address of the rateFeed.\n   * @param tradingMode The trading mode that should be set.\n   */\n  function setRateFeedTradingMode(address rateFeedID, uint8 tradingMode) external;\n\n  /**\n   * @notice Returns addresses of rateFeedIDs that have been added.\n   */\n  function getRateFeeds() external view returns (address[] memory);\n\n  /**\n   * @notice Checks if a breaker is enabled for a specific rate feed.\n   * @param breaker The address of the breaker we're checking for.\n   * @param rateFeedID The address of the rateFeed.\n   */\n  function isBreakerEnabled(address breaker, address rateFeedID) external view returns (bool);\n\n  /**\n   * @notice Sets the address of the sortedOracles contract.\n   * @param _sortedOracles The new address of the sorted oracles contract.\n   */\n  function setSortedOracles(ISortedOracles _sortedOracles) external;\n\n  /// @notice Public state variable getters:\n  function breakerTradingMode(address) external view returns (uint8);\n\n  function sortedOracles() external view returns (address);\n\n  function rateFeedStatus(address) external view returns (bool);\n\n  function owner() external view returns (address);\n\n  function rateFeedBreakerStatus(address, address) external view returns (BreakerStatus memory);\n\n  function rateFeedDependencies(address, uint256) external view returns (address);\n\n  function rateFeedTradingMode(address) external view returns (uint8);\n}\n"},{"file_path":"lib/mento-core/contracts/interfaces/IMarketHoursBreaker.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\ninterface IMarketHoursBreaker {\n  /**\n   * @notice Check if the timestamp is inside FX market hours\n   * @param timestamp The timestamp to check\n   * @return True if the timestamp is inside FX market hours, false otherwise\n   */\n  function isFXMarketOpen(uint256 timestamp) external pure returns (bool);\n\n  /**\n   * @notice  Enforces that the market is open during valid trading hours.\n   *          This function reverts if called outside of FX market hours or on holidays.\n   * @param   rateFeedID The rate feed to be checked. Unused in this implementation as market hours\n   *          in this breaker are not rate feed dependent.\n   * @return  triggerBreaker Always returns false if execution completes (FX market is open),\n   *          And reverts if the FX market is closed.\n   * @dev     This function implements the IBreaker interface but uses a revert-on-condition\n   *          pattern rather than returning true/false. The boolean return is required by the\n   *          interface but will only be reached when the condition passes (FX market open).\n   */\n  function shouldTrigger(address rateFeedID) external view returns (bool triggerBreaker);\n}\n"},{"file_path":"lib/mento-core/contracts/interfaces/IOracleAdapter.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.0;\n\nimport { IBreakerBox } from \"./IBreakerBox.sol\";\nimport { ISortedOracles } from \"./ISortedOracles.sol\";\nimport { IMarketHoursBreaker } from \"./IMarketHoursBreaker.sol\";\nimport { AggregatorV3Interface } from \"foundry-chainlink-toolkit/src/interfaces/feeds/AggregatorV3Interface.sol\";\n\ninterface IOracleAdapter {\n  /* ============================================================ */\n  /* ======================== Structs =========================== */\n  /* ============================================================ */\n\n  /// @notice Struct to store OracleAdapter contract state\n  /// @custom:storage-location erc7201:mento.storage.OracleAdapter\n  struct OracleAdapterStorage {\n    // Contract for querying oracle price feeds\n    ISortedOracles sortedOracles;\n    // Contract for checking trading modes\n    IBreakerBox breakerBox;\n    // Contract for checking market hours\n    IMarketHoursBreaker marketHoursBreaker;\n    // Contract for checking L2 sequencer status\n    AggregatorV3Interface l2SequencerUptimeFeed;\n  }\n\n  /// @notice Struct to store info about a rate\n  struct RateInfo {\n    uint256 numerator;\n    uint256 denominator;\n    uint8 tradingMode;\n    bool isRecent;\n    bool isFXMarketOpen;\n  }\n\n  /* ============================================================ */\n  /* ======================== Errors ============================ */\n  /* ============================================================ */\n\n  // @notice Thrown when the FX market is closed\n  error FXMarketClosed();\n  // @notice Thrown when trading is suspended because of a breaker\n  error TradingSuspended();\n  // @notice Thrown when the rate in sorted oracles is 0\n  error InvalidRate();\n  // @notice Thrown when no recent rate is available\n  error NoRecentRate();\n  // @notice Thrown when trying to set a zero address as a contract address\n  error ZeroAddress();\n\n  /* ============================================================ */\n  /* ======================== Events ============================ */\n  /* ============================================================ */\n\n  /**\n   * @notice Emitted when the SortedOracles contract is updated\n   * @param oldSortedOracles Previous SortedOracles address\n   * @param newSortedOracles New SortedOracles address\n   */\n  event SortedOraclesUpdated(address indexed oldSortedOracles, address indexed newSortedOracles);\n\n  /**\n   * @notice Emitted when the BreakerBox contract is updated\n   * @param oldBreakerBox Previous BreakerBox address\n   * @param newBreakerBox New BreakerBox address\n   */\n  event BreakerBoxUpdated(address indexed oldBreakerBox, address indexed newBreakerBox);\n\n  /**\n   * @notice Emitted when the MarketHoursBreaker contract is updated\n   * @param oldMarketHoursBreaker Previous MarketHoursBreaker address\n   * @param newMarketHoursBreaker New MarketHoursBreaker address\n   */\n  event MarketHoursBreakerUpdated(address indexed oldMarketHoursBreaker, address indexed newMarketHoursBreaker);\n\n  /**\n   * @notice Emitted when the L2 sequencer uptime feed contract is updated\n   * @param oldL2SequencerUptimeFeed Previous L2SequencerUptimeFeed address\n   * @param newL2SequencerUptimeFeed New L2SequencerUptimeFeed address\n   */\n  event L2SequencerUptimeFeedUpdated(\n    address indexed oldL2SequencerUptimeFeed,\n    address indexed newL2SequencerUptimeFeed\n  );\n\n  /* ============================================================ */\n  /* ====================== View Functions ====================== */\n  /* ============================================================ */\n\n  /**\n   * @notice Returns the contract for oracle price feeds\n   * @return Address of the SortedOracles contract\n   */\n  function sortedOracles() external view returns (ISortedOracles);\n\n  /**\n   * @notice Returns the contract for checking trading modes\n   * @return Address of the BreakerBox contract\n   */\n  function breakerBox() external view returns (IBreakerBox);\n\n  /**\n   * @notice Returns the contract for checking market hours\n   * @return Address of the MarketHoursBreaker contract\n   */\n  function marketHoursBreaker() external view returns (IMarketHoursBreaker);\n\n  /**\n   * @notice Returns the contract for checking the L2 sequencer status\n   * @return Address of the L2SequencerUptimeFeed contract\n   */\n  function l2SequencerUptimeFeed() external view returns (AggregatorV3Interface);\n\n  /**\n   * @notice Returns true if the market is open based on FX market hours\n   * @return true if the market is open, false otherwise\n   */\n  function isFXMarketOpen() external view returns (bool);\n\n  /**\n   * @notice Returns true if the rate for a given rate feed ID is recent\n   * @param rateFeedID The address of the rate feed\n   * @return true if the rate is recent, false otherwise\n   */\n  function hasRecentRate(address rateFeedID) external view returns (bool);\n\n  /**\n   * @notice Returns the exchange rate for a given rate feed ID\n   * with 18 decimals of precision, along with other info\n   * @param rateFeedID The address of the rate feed\n   * @return rateInfo The rate info\n   */\n  function getRate(address rateFeedID) external view returns (RateInfo memory);\n\n  /**\n   * @notice Returns the exchange rate for a given rate feed ID\n   * with 18 decimals of precision if considered valid, based on\n   * trading mode, and recent rate, otherwise reverts\n   * @param rateFeedID The address of the rate feed\n   * @return numerator The numerator of the rate\n   * @return denominator The denominator of the rate\n   */\n  function getRateIfValid(address rateFeedID) external view returns (uint256 numerator, uint256 denominator);\n\n  /**\n   * @notice Returns the exchange rate for a given rate feed ID\n   * with 18 decimals of precision if considered valid, based on\n   * FX market hours, trading mode, and recent rate, otherwise reverts\n   * @param rateFeedID The address of the rate feed\n   * @return numerator The numerator of the rate\n   * @return denominator The denominator of the rate\n   */\n  function getFXRateIfValid(address rateFeedID) external view returns (uint256 numerator, uint256 denominator);\n\n  /**\n   * @notice Returns the trading mode for a given rate feed ID\n   * @param rateFeedID The address of the rate feed\n   * @return The trading mode\n   */\n  function getTradingMode(address rateFeedID) external view returns (uint8);\n\n  /**\n   * @notice Ensures that the rate feed is valid by checking trading mode and rate freshness\n   * @dev Reverts if trading is suspended or rate is not recent\n   * @param rateFeedID The address of the rate feed\n   */\n  function ensureRateValid(address rateFeedID) external view;\n\n  /**\n   * @notice Returns true if the L2 sequencer has been up and operational for at least the specified duration.\n   * @param since The minimum number of seconds the L2 sequencer must have been up (e.g., 1 hours = 3600).\n   * @return up True if the sequencer has been up for at least `since` seconds, false otherwise\n   */\n  function isL2SequencerUp(uint256 since) external view returns (bool up);\n\n  /* ============================================================ */\n  /* ==================== Mutative Functions ==================== */\n  /* ============================================================ */\n\n  /**\n   * @notice Initializes the OracleAdapter contract\n   * @param _sortedOracles The address of the sorted oracles contract\n   * @param _breakerBox The address of the breaker box contract\n   * @param _marketHoursBreaker The address of the market hours breaker contract\n   * @param _initialOwner The address to transfer ownership to\n   * @param _l2SequencerUptimeFeed The address of the L2 sequencer uptime feed contract\n   */\n  function initialize(\n    address _sortedOracles,\n    address _breakerBox,\n    address _marketHoursBreaker,\n    address _l2SequencerUptimeFeed,\n    address _initialOwner\n  ) external;\n\n  /**\n   * @notice Sets the address of the sorted oracles contract\n   * @param _sortedOracles The address of the sorted oracles contract\n   */\n  function setSortedOracles(address _sortedOracles) external;\n\n  /**\n   * @notice Sets the address of the breaker box contract\n   * @param _breakerBox The address of the breaker box contract\n   */\n  function setBreakerBox(address _breakerBox) external;\n\n  /**\n   * @notice Sets the address of the market hours breaker contract\n   * @param _marketHoursBreaker The address of the market hours breaker contract\n   */\n  function setMarketHoursBreaker(address _marketHoursBreaker) external;\n\n  /**\n   * @notice Sets the address of the L2 sequencer uptime feed contract\n   * @param _l2SequencerUptimeFeed The address of the L2 sequencer uptime feed contract\n   */\n  function setL2SequencerUptimeFeed(address _l2SequencerUptimeFeed) external;\n}\n"},{"file_path":"lib/mento-core/contracts/interfaces/ISortedOracles.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity >0.5.13 <0.9;\n\nimport { IBreakerBox } from \"./IBreakerBox.sol\";\n\ninterface ISortedOracles {\n  enum MedianRelation {\n    Undefined,\n    Lesser,\n    Greater,\n    Equal\n  }\n\n  function isOracle(address, address) external view returns (bool);\n\n  function addOracle(address, address) external;\n\n  function removeOracle(address, address, uint256) external;\n\n  function report(address, uint256, address, address) external;\n\n  function removeExpiredReports(address, uint256) external;\n\n  function isOldestReportExpired(address token) external view returns (bool, address);\n\n  function numRates(address) external view returns (uint256);\n\n  function medianRate(address) external view returns (uint256, uint256);\n\n  function numTimestamps(address) external view returns (uint256);\n\n  function medianTimestamp(address) external view returns (uint256);\n\n  function getOracles(address) external view returns (address[] memory);\n\n  function getRates(address token) external view returns (address[] memory, uint256[] memory, MedianRelation[] memory);\n\n  function getTimestamps(\n    address token\n  ) external view returns (address[] memory, uint256[] memory, MedianRelation[] memory);\n\n  function initialize(uint256) external;\n\n  function setBreakerBox(IBreakerBox) external;\n\n  function reportExpirySeconds() external view returns (uint256);\n\n  function getTokenReportExpirySeconds(address token) external view returns (uint256);\n\n  function oracles(address, uint256) external view returns (address);\n\n  function breakerBox() external view returns (IBreakerBox);\n}\n"},{"file_path":"lib/mento-core/lib/foundry-chainlink-toolkit/src/interfaces/feeds/AggregatorV3Interface.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2 <0.9.0;\n\ninterface AggregatorV3Interface {\n  function decimals() external view returns (uint8);\n  function description() external view returns (string memory);\n  function version() external view returns (uint256);\n  function getRoundData(uint80 _roundId) external view returns (\n    uint80 roundId,\n    int256 answer,\n    uint256 startedAt,\n    uint256 updatedAt,\n    uint80 answeredInRound\n  );\n  function latestRoundData() external view returns (\n    uint80 roundId,\n    int256 answer,\n    uint256 startedAt,\n    uint256 updatedAt,\n    uint80 answeredInRound\n  );\n}\n"},{"file_path":"lib/mento-core/lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal onlyInitializing {\n        __Ownable_init_unchained();\n    }\n\n    function __Ownable_init_unchained() internal onlyInitializing {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"},{"file_path":"lib/mento-core/lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"},{"file_path":"lib/mento-core/lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"},{"file_path":"lib/mento-core/lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[50] private __gap;\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"bool","name":"disable","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"FXMarketClosed","type":"error"},{"inputs":[],"name":"InvalidRate","type":"error"},{"inputs":[],"name":"NoRecentRate","type":"error"},{"inputs":[],"name":"TradingSuspended","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldBreakerBox","type":"address"},{"indexed":true,"internalType":"address","name":"newBreakerBox","type":"address"}],"name":"BreakerBoxUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldL2SequencerUptimeFeed","type":"address"},{"indexed":true,"internalType":"address","name":"newL2SequencerUptimeFeed","type":"address"}],"name":"L2SequencerUptimeFeedUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldMarketHoursBreaker","type":"address"},{"indexed":true,"internalType":"address","name":"newMarketHoursBreaker","type":"address"}],"name":"MarketHoursBreakerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldSortedOracles","type":"address"},{"indexed":true,"internalType":"address","name":"newSortedOracles","type":"address"}],"name":"SortedOraclesUpdated","type":"event"},{"inputs":[],"name":"TRADING_MODE_BIDIRECTIONAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"breakerBox","outputs":[{"internalType":"contract IBreakerBox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rateFeedID","type":"address"}],"name":"ensureRateValid","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rateFeedID","type":"address"}],"name":"getFXRateIfValid","outputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rateFeedID","type":"address"}],"name":"getRate","outputs":[{"components":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"},{"internalType":"uint8","name":"tradingMode","type":"uint8"},{"internalType":"bool","name":"isRecent","type":"bool"},{"internalType":"bool","name":"isFXMarketOpen","type":"bool"}],"internalType":"struct IOracleAdapter.RateInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rateFeedID","type":"address"}],"name":"getRateIfValid","outputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rateFeedID","type":"address"}],"name":"getTradingMode","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"rateFeedID","type":"address"}],"name":"hasRecentRate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sortedOracles","type":"address"},{"internalType":"address","name":"_breakerBox","type":"address"},{"internalType":"address","name":"_marketHoursBreaker","type":"address"},{"internalType":"address","name":"_l2SequencerUptimeFeed","type":"address"},{"internalType":"address","name":"_initialOwner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isFXMarketOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"since","type":"uint256"}],"name":"isL2SequencerUp","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l2SequencerUptimeFeed","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketHoursBreaker","outputs":[{"internalType":"contract IMarketHoursBreaker","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_breakerBox","type":"address"}],"name":"setBreakerBox","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_l2SequencerUptimeFeed","type":"address"}],"name":"setL2SequencerUptimeFeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marketHoursBreaker","type":"address"}],"name":"setMarketHoursBreaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_sortedOracles","type":"address"}],"name":"setSortedOracles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sortedOracles","outputs":[{"internalType":"contract ISortedOracles","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"0000000000000000000000000000000000000000000000000000000000000001"}