FRAX Price: $1.04 (+6.91%)

Contract

0x4b0Ca693e29e5FD2AA39332a0387BBCD0f91a527

Overview

FRAX Balance | FXTL Balance

0 FRAX | 9,813 FXTL

FRAX Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To

There are no matching entries

> 10 Internal Transactions and > 10 Token Transfers found.

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
312090072026-01-24 4:25:2516 hrs ago1769228725
0x4b0Ca693...D0f91a527
0 FRAX
312090072026-01-24 4:25:2516 hrs ago1769228725
0x4b0Ca693...D0f91a527
0 FRAX
312090072026-01-24 4:25:2516 hrs ago1769228725
0x4b0Ca693...D0f91a527
0 FRAX
312090072026-01-24 4:25:2516 hrs ago1769228725
0x4b0Ca693...D0f91a527
0 FRAX
312090072026-01-24 4:25:2516 hrs ago1769228725
0x4b0Ca693...D0f91a527
0 FRAX
312090072026-01-24 4:25:2516 hrs ago1769228725
0x4b0Ca693...D0f91a527
0 FRAX
312090072026-01-24 4:25:2516 hrs ago1769228725
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312065252026-01-24 3:02:4118 hrs ago1769223761
0x4b0Ca693...D0f91a527
0 FRAX
312037692026-01-24 1:30:4919 hrs ago1769218249
0x4b0Ca693...D0f91a527
0 FRAX
312037692026-01-24 1:30:4919 hrs ago1769218249
0x4b0Ca693...D0f91a527
0 FRAX
312037692026-01-24 1:30:4919 hrs ago1769218249
0x4b0Ca693...D0f91a527
0 FRAX
312037692026-01-24 1:30:4919 hrs ago1769218249
0x4b0Ca693...D0f91a527
0 FRAX
312037692026-01-24 1:30:4919 hrs ago1769218249
0x4b0Ca693...D0f91a527
0 FRAX
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FrxEthDualOracle

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
shanghai EvmVersion
// SPDX-License-Identifier: ISC
pragma solidity ^0.8.20;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ======================== FrxEthDualOracle =========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// ====================================================================

import { Timelock2Step } from "frax-std/access-control/v1/Timelock2Step.sol";
import { ITimelock2Step } from "frax-std/access-control/v1/interfaces/ITimelock2Step.sol";
import { UniswapV3SingleTwapOracle, ConstructorParams as UniswapV3SingleTwapOracleParams } from "../abstracts/UniswapV3SingleTwapOracle.sol";
import { ChainlinkOracleWithMaxDelay, ConstructorParams as ChainlinkOracleWithMaxDelayParams } from "../abstracts/ChainlinkOracleWithMaxDelay.sol";
import { EthUsdChainlinkOracleWithMaxDelay, ConstructorParams as EthUsdChainlinkOracleWithMaxDelayParams } from "../abstracts/EthUsdChainlinkOracleWithMaxDelay.sol";
import { DualOracleBase, ConstructorParams as DualOracleBaseParams } from "../DualOracleBase.sol";
import { FraxSwapTwapOracle, ConstructorParams as FraxSwapOracleParams } from "../abstracts/FraxSwapTwapPriceOracle.sol";
import "interfaces/IDualOracle.sol";

struct ConstructorParams {
    address fraxswapPair;
    uint32 twapDuration;
    address frxEthErc20;
    address frxEthUsdChainlinkFeed;
    uint256 maximumOracleDelay;
    address timelockAddress;
}

/// @title FrxEthDualOracle
contract FrxEthDualOracle is DualOracleBase, Timelock2Step, FraxSwapTwapOracle, EthUsdChainlinkOracleWithMaxDelay {
    address public immutable FRXETH_ERC20;

    constructor(
        ConstructorParams memory _params
    )
        DualOracleBase(
            DualOracleBaseParams({
                baseToken0: address(840),
                baseToken0Decimals: 18,
                quoteToken0: _params.frxEthErc20,
                quoteToken0Decimals: 18,
                baseToken1: address(840),
                baseToken1Decimals: 18,
                quoteToken1: _params.frxEthErc20,
                quoteToken1Decimals: 18
            })
        )
        Timelock2Step()
        EthUsdChainlinkOracleWithMaxDelay(
            EthUsdChainlinkOracleWithMaxDelayParams({
                ethUsdChainlinkFeedAddress: _params.frxEthUsdChainlinkFeed,
                maxEthUsdOracleDelay: _params.maximumOracleDelay
            })
        )
        FraxSwapTwapOracle(
            FraxSwapOracleParams({
                fraxswapPair: _params.fraxswapPair,
                toQuote: _params.frxEthErc20,
                twapDuration: _params.twapDuration
            })
        )
    {
        _setTimelock({ _newTimelock: _params.timelockAddress });
        _registerInterface({ interfaceId: type(IDualOracle).interfaceId });
        _registerInterface({ interfaceId: type(ITimelock2Step).interfaceId });

        FRXETH_ERC20 = _params.frxEthErc20;
    }

    // ====================================================================
    // View Helpers
    // ====================================================================

    function name() external pure returns (string memory) {
        return "FrxEth RedStone Dual Oracle + TWAP";
    }

    // ====================================================================
    // Configuration Setters
    // ====================================================================

    /// @notice The ```setMaximumEthUsdOracleDelay``` function set the max oracle delay for the Eth/USD Redstone oracle
    /// @dev Requires msg.sender to be the timelock address
    /// @param _newMaxOracleDelay The new max oracle delay
    function setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) external override {
        _requireTimelock();
        _setMaximumEthUsdOracleDelay({ _newMaxOracleDelay: _newMaxOracleDelay });
    }

    /// @notice The ```setTwapDurationFraxSwap``` function set the twap duration for the FraxSwap Twap Oracle
    /// @dev Requiores msg.sender to be the timelock address
    /// @param _newTwapDuration The new twap duration
    function setTwapDurationFraxSwap(uint32 _newTwapDuration) external override {
        _requireTimelock();
        _setTwapDurationFraxSwap({ _newTwapDuration: _newTwapDuration });
    }

    // ====================================================================
    // Price Functions
    // ====================================================================

    /// @notice The ```getEthPerUsdRedStone``` function returns the amount of eth per 1 USD
    /// @return _isBadData Whether the data returned from the oracle is stale
    /// @return _ethPerUsd The amount of eth per unit of USD
    function getEthPerUsdRedStone() public view returns (bool _isBadData, uint256 _ethPerUsd) {
        (bool isBadData, , uint256 usdPerEth) = _getEthUsdChainlinkPrice();
        _isBadData = isBadData;
        _ethPerUsd = (ETH_USD_CHAINLINK_FEED_PRECISION * ORACLE_PRECISION) / usdPerEth;
    }

    /// @notice The ```getPricesNormalized``` function returns the normalized prices in human readable form
    /// @return _isBadDataNormal If the Redstone oracle is stale
    /// @return _priceLowNormal The normalized low price
    /// @return _priceHighNormal The normalized high price
    function getPricesNormalized()
        external
        view
        returns (bool _isBadDataNormal, uint256 _priceLowNormal, uint256 _priceHighNormal)
    {
        (bool _isBadData, uint256 _priceLow, uint256 _priceHigh) = _getPrices();
        _isBadDataNormal = _isBadData;

        _priceLowNormal = NORMALIZATION_0 > 0
            ? _priceLow * 10 ** uint256(NORMALIZATION_0)
            : _priceLow / 10 ** (uint256(-NORMALIZATION_0));

        _priceHighNormal = NORMALIZATION_1 > 0
            ? _priceHigh * 10 ** uint256(NORMALIZATION_1)
            : _priceHigh / 10 ** (uint256(-NORMALIZATION_1));
    }

    function _getPrices() internal view returns (bool _isBadData, uint256 _priceLow, uint256 _priceHigh) {
        (bool isBadData, uint256 _ethPerUsdRedStone) = getEthPerUsdRedStone();

        uint256 _fraxPerEthTwap = _getTwapFraxSwapPair();
        uint256 _ethPerFraxTwap = (ORACLE_PRECISION ** 2) / _fraxPerEthTwap;

        _isBadData = isBadData;
        _priceLow = _ethPerFraxTwap < _ethPerUsdRedStone ? _ethPerFraxTwap : _ethPerUsdRedStone;
        _priceHigh = _ethPerUsdRedStone > _ethPerFraxTwap ? _ethPerUsdRedStone : _ethPerFraxTwap;
    }

    /// @notice The ```getPrices``` function is intended to return two prices from different oracles
    /// @return _isBadData is true when data is stale or otherwise bad
    /// @return _priceLow is the lower of the two prices
    /// @return _priceHigh is the higher of the two prices
    function getPrices() external view returns (bool _isBadData, uint256 _priceLow, uint256 _priceHigh) {
        return _getPrices();
    }
}

// SPDX-License-Identifier: ISC
pragma solidity >=0.8.0;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ========================== Timelock2Step ===========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// Primary Author
// Drake Evans: https://github.com/DrakeEvans

// Reviewers
// Dennis: https://github.com/denett

// ====================================================================

/// @title Timelock2Step
/// @author Drake Evans (Frax Finance) https://github.com/drakeevans
/// @dev Inspired by the OpenZeppelin's Ownable2Step contract
/// @notice  An abstract contract which contains 2-step transfer and renounce logic for a timelock address
abstract contract Timelock2Step {
    /// @notice The pending timelock address
    address public pendingTimelockAddress;

    /// @notice The current timelock address
    address public timelockAddress;

    constructor() {
        timelockAddress = msg.sender;
    }

    /// @notice Emitted when timelock is transferred
    error OnlyTimelock();

    /// @notice Emitted when pending timelock is transferred
    error OnlyPendingTimelock();

    /// @notice The ```TimelockTransferStarted``` event is emitted when the timelock transfer is initiated
    /// @param previousTimelock The address of the previous timelock
    /// @param newTimelock The address of the new timelock
    event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock);

    /// @notice The ```TimelockTransferred``` event is emitted when the timelock transfer is completed
    /// @param previousTimelock The address of the previous timelock
    /// @param newTimelock The address of the new timelock
    event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock);

    /// @notice The ```_isSenderTimelock``` function checks if msg.sender is current timelock address
    /// @return Whether or not msg.sender is current timelock address
    function _isSenderTimelock() internal view returns (bool) {
        return msg.sender == timelockAddress;
    }

    /// @notice The ```_requireTimelock``` function reverts if msg.sender is not current timelock address
    function _requireTimelock() internal view {
        if (msg.sender != timelockAddress) revert OnlyTimelock();
    }

    /// @notice The ```_isSenderPendingTimelock``` function checks if msg.sender is pending timelock address
    /// @return Whether or not msg.sender is pending timelock address
    function _isSenderPendingTimelock() internal view returns (bool) {
        return msg.sender == pendingTimelockAddress;
    }

    /// @notice The ```_requirePendingTimelock``` function reverts if msg.sender is not pending timelock address
    function _requirePendingTimelock() internal view {
        if (msg.sender != pendingTimelockAddress) revert OnlyPendingTimelock();
    }

    /// @notice The ```_transferTimelock``` function initiates the timelock transfer
    /// @dev This function is to be implemented by a public function
    /// @param _newTimelock The address of the nominated (pending) timelock
    function _transferTimelock(address _newTimelock) internal {
        pendingTimelockAddress = _newTimelock;
        emit TimelockTransferStarted(timelockAddress, _newTimelock);
    }

    /// @notice The ```_acceptTransferTimelock``` function completes the timelock transfer
    /// @dev This function is to be implemented by a public function
    function _acceptTransferTimelock() internal {
        pendingTimelockAddress = address(0);
        _setTimelock(msg.sender);
    }

    /// @notice The ```_setTimelock``` function sets the timelock address
    /// @dev This function is to be implemented by a public function
    /// @param _newTimelock The address of the new timelock
    function _setTimelock(address _newTimelock) internal {
        emit TimelockTransferred(timelockAddress, _newTimelock);
        timelockAddress = _newTimelock;
    }

    /// @notice The ```transferTimelock``` function initiates the timelock transfer
    /// @dev Must be called by the current timelock
    /// @param _newTimelock The address of the nominated (pending) timelock
    function transferTimelock(address _newTimelock) external virtual {
        _requireTimelock();
        _transferTimelock(_newTimelock);
    }

    /// @notice The ```acceptTransferTimelock``` function completes the timelock transfer
    /// @dev Must be called by the pending timelock
    function acceptTransferTimelock() external virtual {
        _requirePendingTimelock();
        _acceptTransferTimelock();
    }

    /// @notice The ```renounceTimelock``` function renounces the timelock after setting pending timelock to current timelock
    /// @dev Pending timelock must be set to current timelock before renouncing, creating a 2-step renounce process
    function renounceTimelock() external virtual {
        _requireTimelock();
        _requirePendingTimelock();
        _transferTimelock(address(0));
        _setTimelock(address(0));
    }
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.0;

interface ITimelock2Step {
    event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock);
    event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock);

    function acceptTransferTimelock() external;

    function pendingTimelockAddress() external view returns (address);

    function renounceTimelock() external;

    function timelockAddress() external view returns (address);

    function transferTimelock(address _newTimelock) external;
}

// SPDX-License-Identifier: ISC
pragma solidity ^0.8.20;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ==================== UniswapV3SingleTwapOracle =====================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// Author
// Drake Evans: https://github.com/DrakeEvans

// Reviewers
// Dennis: https://github.com/denett

// ====================================================================

import { IStaticOracle } from "@mean-finance/uniswap-v3-oracle/solidity/interfaces/IStaticOracle.sol";
import { ERC165Storage } from "src/contracts/utils/ERC165Storage.sol";
import { IUniswapV3SingleTwapOracle } from "interfaces/oracles/abstracts/IUniswapV3SingleTwapOracle.sol";

struct ConstructorParams {
    address uniswapV3PairAddress;
    uint32 twapDuration;
    address baseToken;
    address quoteToken;
}

/// @title UniswapV3SingleTwapOracle
/// @author Drake Evans (Frax Finance) https://github.com/drakeevans
/// @notice  An oracle for UniV3 Twap prices
abstract contract UniswapV3SingleTwapOracle is ERC165Storage, IUniswapV3SingleTwapOracle {
    /// @notice address of the Uniswap V3 pair
    address public immutable UNI_V3_PAIR_ADDRESS;

    /// @notice The precision of the twap
    uint128 public constant TWAP_PRECISION = 1e18;

    /// @notice The base token of the twap
    address public immutable UNISWAP_V3_TWAP_BASE_TOKEN;

    /// @notice The quote token of the twap
    address public immutable UNISWAP_V3_TWAP_QUOTE_TOKEN;

    /// @notice The duration of the twap
    uint32 public twapDuration;

    constructor(ConstructorParams memory _params) {
        _registerInterface({ interfaceId: type(IUniswapV3SingleTwapOracle).interfaceId });

        UNI_V3_PAIR_ADDRESS = _params.uniswapV3PairAddress;
        twapDuration = _params.twapDuration;
        UNISWAP_V3_TWAP_BASE_TOKEN = _params.baseToken;
        UNISWAP_V3_TWAP_QUOTE_TOKEN = _params.quoteToken;
    }

    /// @notice The ```_setTwapDuration``` function sets duration of the twap
    /// @param _newTwapDuration The new twap duration
    function _setTwapDuration(uint32 _newTwapDuration) internal {
        emit SetTwapDuration({ oldTwapDuration: twapDuration, newTwapDuration: _newTwapDuration });
        twapDuration = _newTwapDuration;
    }

    function setTwapDuration(uint32 _newTwapDuration) external virtual;

    /// @notice The ```_getUniswapV3Twap``` function is called to get the twap
    /// @return _twap The twap price
    function _getUniswapV3Twap() internal view returns (uint256 _twap) {
        address[] memory _pools = new address[](1);
        _pools[0] = UNI_V3_PAIR_ADDRESS;

        _twap = IStaticOracle(0xB210CE856631EeEB767eFa666EC7C1C57738d438).quoteSpecificPoolsWithTimePeriod({
            baseAmount: TWAP_PRECISION,
            baseToken: UNISWAP_V3_TWAP_BASE_TOKEN,
            quoteToken: UNISWAP_V3_TWAP_QUOTE_TOKEN,
            pools: _pools,
            period: twapDuration
        });
    }

    /// @notice The ```getUniswapV3Twap``` function is called to get the twap
    /// @return _twap The twap price
    function getUniswapV3Twap() external view virtual returns (uint256 _twap) {
        _twap = _getUniswapV3Twap();
    }
}

// SPDX-License-Identifier: ISC
pragma solidity ^0.8.20;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// =================== ChainlinkOracleWithMaxDelay ====================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// Author
// Drake Evans: https://github.com/DrakeEvans

// Reviewers
// Dennis: https://github.com/denett

// ====================================================================

import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import { ERC165Storage } from "src/contracts/utils/ERC165Storage.sol";
import { IChainlinkOracleWithMaxDelay } from "interfaces/oracles/abstracts/IChainlinkOracleWithMaxDelay.sol";

struct ConstructorParams {
    address chainlinkFeedAddress;
    uint256 maximumOracleDelay;
}

/// @title ChainlinkOracleWithMaxDelay
/// @author Drake Evans (Frax Finance) https://github.com/drakeevans
/// @notice  An abstract oracle for getting prices from Chainlink
abstract contract ChainlinkOracleWithMaxDelay is ERC165Storage, IChainlinkOracleWithMaxDelay {
    /// @notice Chainlink aggregator
    address public immutable CHAINLINK_FEED_ADDRESS;

    /// @notice Decimals of ETH/USD chainlink feed
    uint8 public immutable CHAINLINK_FEED_DECIMALS;

    /// @notice Precision of ETH/USD chainlink feed
    uint256 public immutable CHAINLINK_FEED_PRECISION;

    /// @notice Maximum delay of Chainlink data, after which it is considered stale
    uint256 public maximumOracleDelay;

    constructor(ConstructorParams memory _params) {
        _registerInterface({ interfaceId: type(IChainlinkOracleWithMaxDelay).interfaceId });

        CHAINLINK_FEED_ADDRESS = _params.chainlinkFeedAddress;
        CHAINLINK_FEED_DECIMALS = AggregatorV3Interface(CHAINLINK_FEED_ADDRESS).decimals();
        CHAINLINK_FEED_PRECISION = 10 ** uint256(CHAINLINK_FEED_DECIMALS);
        maximumOracleDelay = _params.maximumOracleDelay;
    }

    /// @notice The ```SetMaximumOracleDelay``` event is emitted when the max oracle delay is set
    /// @param oldMaxOracleDelay The old max oracle delay
    /// @param newMaxOracleDelay The new max oracle delay
    event SetMaximumOracleDelay(uint256 oldMaxOracleDelay, uint256 newMaxOracleDelay);

    /// @notice The ```_setMaximumOracleDelay``` function sets the max oracle delay to determine if Chainlink data is stale
    /// @param _newMaxOracleDelay The new max oracle delay
    function _setMaximumOracleDelay(uint256 _newMaxOracleDelay) internal {
        emit SetMaximumOracleDelay({ oldMaxOracleDelay: maximumOracleDelay, newMaxOracleDelay: _newMaxOracleDelay });
        maximumOracleDelay = _newMaxOracleDelay;
    }

    function setMaximumOracleDelay(uint256 _newMaxOracleDelay) external virtual;

    function _getChainlinkPrice() internal view returns (bool _isBadData, uint256 _updatedAt, uint256 _price) {
        (, int256 _answer, , uint256 _chainlinkUpdatedAt, ) = AggregatorV3Interface(CHAINLINK_FEED_ADDRESS)
            .latestRoundData();

        // If data is stale or negative, set bad data to true and return
        _isBadData = _answer <= 0 || ((block.timestamp - _chainlinkUpdatedAt) > maximumOracleDelay);
        _updatedAt = _chainlinkUpdatedAt;
        _price = uint256(_answer);
    }

    /// @notice The ```getChainlinkPrice``` function returns the chainlink price and the timestamp of the last update
    /// @dev Uses the same prevision as the chainlink feed, virtual so it can be overridden
    /// @return _isBadData True if the data is stale or negative
    /// @return _updatedAt The timestamp of the last update
    /// @return _price The price
    function getChainlinkPrice() external view virtual returns (bool _isBadData, uint256 _updatedAt, uint256 _price) {
        return _getChainlinkPrice();
    }
}

// SPDX-License-Identifier: ISC
pragma solidity ^0.8.20;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ================ EthUsdChainlinkOracleWithMaxDelay =================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// Author
// Drake Evans: https://github.com/DrakeEvans

// Reviewers
// Dennis: https://github.com/denett

// ====================================================================

import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import { ERC165Storage } from "src/contracts/utils/ERC165Storage.sol";
import { IEthUsdChainlinkOracleWithMaxDelay } from "interfaces/oracles/abstracts/IEthUsdChainlinkOracleWithMaxDelay.sol";

struct ConstructorParams {
    address ethUsdChainlinkFeedAddress;
    uint256 maxEthUsdOracleDelay;
}

/// @title EthUsdChainlinkOracleWithMaxDelay
/// @author Drake Evans (Frax Finance) https://github.com/drakeevans
/// @notice  An abstract oracle for getting eth/usd prices from Chainlink
abstract contract EthUsdChainlinkOracleWithMaxDelay is ERC165Storage, IEthUsdChainlinkOracleWithMaxDelay {
    /// @notice Chainlink aggregator
    address public immutable ETH_USD_CHAINLINK_FEED_ADDRESS;

    /// @notice Decimals of ETH/USD chainlink feed
    uint8 public immutable ETH_USD_CHAINLINK_FEED_DECIMALS;

    /// @notice Precision of ETH/USD chainlink feed
    uint256 public immutable ETH_USD_CHAINLINK_FEED_PRECISION;

    /// @notice Maximum delay of Chainlink data, after which it is considered stale
    uint256 public maximumEthUsdOracleDelay;

    constructor(ConstructorParams memory _params) {
        _registerInterface({ interfaceId: type(IEthUsdChainlinkOracleWithMaxDelay).interfaceId });

        ETH_USD_CHAINLINK_FEED_ADDRESS = _params.ethUsdChainlinkFeedAddress;
        ETH_USD_CHAINLINK_FEED_DECIMALS = AggregatorV3Interface(ETH_USD_CHAINLINK_FEED_ADDRESS).decimals();
        ETH_USD_CHAINLINK_FEED_PRECISION = 10 ** uint256(ETH_USD_CHAINLINK_FEED_DECIMALS);
        maximumEthUsdOracleDelay = _params.maxEthUsdOracleDelay;
    }

    /// @notice The ```_setMaximumEthUsdOracleDelay``` function sets the max oracle delay to determine if Chainlink data is stale
    /// @param _newMaxOracleDelay The new max oracle delay
    function _setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) internal {
        emit SetMaximumEthUsdOracleDelay({
            oldMaxOracleDelay: maximumEthUsdOracleDelay,
            newMaxOracleDelay: _newMaxOracleDelay
        });
        maximumEthUsdOracleDelay = _newMaxOracleDelay;
    }

    function setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) external virtual;

    /// @notice The ```_getEthUsdChainlinkPrice``` function is called to get the eth/usd price from Chainlink
    /// @dev If data is stale or negative, set bad data to true and return
    /// @return _isBadData If the data is stale
    /// @return _updatedAt The timestamp of the last update
    /// @return _usdPerEth The eth/usd price
    function _getEthUsdChainlinkPrice()
        internal
        view
        returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth)
    {
        (, int256 _answer, , uint256 _ethUsdChainlinkUpdatedAt, ) = AggregatorV3Interface(
            ETH_USD_CHAINLINK_FEED_ADDRESS
        ).latestRoundData();

        // If data is stale or negative, set bad data to true and return
        _isBadData = _answer <= 0 || ((block.timestamp - _ethUsdChainlinkUpdatedAt) > maximumEthUsdOracleDelay);
        _updatedAt = _ethUsdChainlinkUpdatedAt;
        _usdPerEth = uint256(_answer);
    }

    /// @notice The ```getEthUsdChainlinkPrice``` function is called to get the eth/usd price from Chainlink
    /// @return _isBadData If the data is stale
    /// @return _updatedAt The timestamp of the last update
    /// @return _usdPerEth The eth/usd price
    function getEthUsdChainlinkPrice()
        external
        view
        virtual
        returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth)
    {
        (_isBadData, _updatedAt, _usdPerEth) = _getEthUsdChainlinkPrice();
    }
}

File 7 of 23 : DualOracleBase.sol
// SPDX-License-Identifier: ISC
pragma solidity ^0.8.20;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ========================== DualOracleBase ==========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// Author
// Drake Evans: https://github.com/DrakeEvans

// ====================================================================

import "interfaces/IDualOracle.sol";

struct ConstructorParams {
    address baseToken0;
    uint8 baseToken0Decimals;
    address quoteToken0;
    uint8 quoteToken0Decimals;
    address baseToken1;
    uint8 baseToken1Decimals;
    address quoteToken1;
    uint8 quoteToken1Decimals;
}

/// @title DualOracleBase
/// @author Drake Evans (Frax Finance) https://github.com/drakeevans
/// @notice  Base Contract for Frax Dual Oracles
abstract contract DualOracleBase is IDualOracle {
    /// @notice The precision of the oracle
    uint256 public constant ORACLE_PRECISION = 1e18;

    /// @notice The first quote token
    address public immutable QUOTE_TOKEN_0;

    /// @notice The first quote token decimals
    uint256 public immutable QUOTE_TOKEN_0_DECIMALS;

    /// @notice The second quote token
    address public immutable QUOTE_TOKEN_1;

    /// @notice The second quote token decimals
    uint256 public immutable QUOTE_TOKEN_1_DECIMALS;

    /// @notice The first base token
    address public immutable BASE_TOKEN_0;

    /// @notice The first base token decimals
    uint256 public immutable BASE_TOKEN_0_DECIMALS;

    /// @notice The second base token
    address public immutable BASE_TOKEN_1;

    /// @notice The second base token decimals
    uint256 public immutable BASE_TOKEN_1_DECIMALS;

    /// @notice The first normalization factor which accounts for different decimals across ERC20s
    /// @dev Normalization = quoteTokenDecimals - baseTokenDecimals
    int256 public immutable NORMALIZATION_0;

    /// @notice The second normalization factor which accounts for different decimals across ERC20s
    /// @dev Normalization = quoteTokenDecimals - baseTokenDecimals
    int256 public immutable NORMALIZATION_1;

    constructor(ConstructorParams memory _params) {
        QUOTE_TOKEN_0 = _params.quoteToken0;
        QUOTE_TOKEN_0_DECIMALS = _params.quoteToken0Decimals;
        QUOTE_TOKEN_1 = _params.quoteToken1;
        QUOTE_TOKEN_1_DECIMALS = _params.quoteToken1Decimals;
        BASE_TOKEN_0 = _params.baseToken0;
        BASE_TOKEN_0_DECIMALS = _params.baseToken0Decimals;
        BASE_TOKEN_1 = _params.baseToken1;
        BASE_TOKEN_1_DECIMALS = _params.baseToken1Decimals;
        NORMALIZATION_0 = int256(QUOTE_TOKEN_0_DECIMALS) - int256(BASE_TOKEN_0_DECIMALS);
        NORMALIZATION_1 = int256(QUOTE_TOKEN_1_DECIMALS) - int256(BASE_TOKEN_1_DECIMALS);
    }

    // ====================================================================
    // View Helpers
    // ====================================================================

    function decimals() external pure returns (uint8) {
        return 18;
    }
}

// SPDX-License-Identifier: ISC
pragma solidity ^0.8.20;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ======================= FraxswapTwapOracle =========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// ====================================================================

import { ERC165Storage } from "src/contracts/utils/ERC165Storage.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { IFraxswapPair } from "dev-fraxswap/src/contracts/core/interfaces/IFraxswapPair.sol";
import { UQ112x112 } from "src/contracts/utils/UQ112x112.sol";

struct ConstructorParams {
    address fraxswapPair;
    address toQuote;
    uint32 twapDuration;
}

/// @title FraxSwapTwapOracle
/// @notice Will fetch the twap price of the quote asset denominated in the base token
/// @notice Only intended to work for pairs in which both of the assets have 18 decimals
abstract contract FraxSwapTwapOracle is ERC165Storage {
    /// @notice Fraxswap Pair to source twap
    IFraxswapPair public immutable FRAXSWAP_PAIR;

    /// @notice The token in the fraxswap pair which the price of the base token is denominated in
    address public FRAXSWAP_BASE_TOKEN;

    /// @notice The token in the fraxswap pair which we would like the twap of
    address public FRAXSWAP_QUOTE_TOKEN;

    /// @notice The duration of the time wieghted moving average is
    uint32 public twapDuration;

    /// @notice flow control to perform the operation on token0|token1 accounting
    bool isToken0;

    using UQ112x112 for uint224;

    constructor(ConstructorParams memory _params) {
        // Fraxswap Oracle Config
        FRAXSWAP_PAIR = IFraxswapPair(_params.fraxswapPair);
        twapDuration = _params.twapDuration;
        address token0 = FRAXSWAP_PAIR.token0();
        address token1 = FRAXSWAP_PAIR.token1();

        if (token0 == _params.toQuote) {
            isToken0 = true;
            FRAXSWAP_QUOTE_TOKEN = _params.toQuote;
            FRAXSWAP_BASE_TOKEN = token1;
        } else if (token1 == _params.toQuote) {
            // isToken0 initalizes to false
            FRAXSWAP_QUOTE_TOKEN = _params.toQuote;
            FRAXSWAP_BASE_TOKEN = token0;
        } else {
            revert TokenNotInPair();
        }

        // Sanity check tokens
        if (FRAXSWAP_PAIR.getTWAPHistoryLength() < 5) revert PairNotOldEnough();
        if (IERC20Metadata(token0).decimals() != 18) revert WrongDecimals();
        if (IERC20Metadata(token1).decimals() != 18) revert WrongDecimals();
    }

    // ====================================================================
    // Post Construction Setters
    // ====================================================================

    function setTwapDurationFraxSwap(uint32 _newTwapDuration) external virtual;

    /// @notice The ```_setTwapDurationFraxSwap``` function is called to modify the twap duration post deployment
    /// @dev Contains no access control
    /// @param _newTwapDuration The new twap duration to set
    function _setTwapDurationFraxSwap(uint32 _newTwapDuration) internal {
        emit NewTwapDurationSet(twapDuration, _newTwapDuration);
        twapDuration = _newTwapDuration;
    }

    // ====================================================================
    // Twap Pricinge Function
    // ====================================================================

    /// @notice The ```_getTwapFraxSwapPair``` function is called to get the twap of the fraxswap pair
    /// @return _basePerQuote returns the amount of base token per quote token
    function _getTwapFraxSwapPair() public view virtual returns (uint256 _basePerQuote) {
        uint256 len = FRAXSWAP_PAIR.getTWAPHistoryLength();
        IFraxswapPair.TWAPObservation memory obsCurrent = FRAXSWAP_PAIR.TWAPObservationHistory(len - 1);

        // Update last observation up to the current block
        if (obsCurrent.timestamp < block.timestamp) {
            // Update the reserves
            (uint112 _reserve0, uint112 _reserve1, ) = FRAXSWAP_PAIR.getReserves();
            uint32 blockTimestamp = uint32(block.timestamp % 2 ** 32);
            // Get the latest observed prices
            unchecked {
                uint32 timeElapsed = blockTimestamp - uint32(obsCurrent.timestamp);
                obsCurrent.price0CumulativeLast += uint256(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
                obsCurrent.price1CumulativeLast += uint256(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
                obsCurrent.timestamp = blockTimestamp;
            }
        }

        IFraxswapPair.TWAPObservation memory obsLast;

        uint256 j;
        // Cannot be > 1 obs per second and > 1 block per second
        for (uint256 i = twapDuration / 40; i < twapDuration; i += twapDuration / 20) {
            obsLast = FRAXSWAP_PAIR.TWAPObservationHistory(len - (1 + i));
            unchecked {
                if ((obsCurrent.timestamp - obsLast.timestamp) < twapDuration) {
                    j = i;
                } else {
                    break;
                }
            }
        }
        for (j; j < len; j++) {
            obsLast = FRAXSWAP_PAIR.TWAPObservationHistory(len - (1 + j));
            unchecked {
                if ((obsCurrent.timestamp - obsLast.timestamp) > twapDuration) break;
            }
        }
        if (isToken0) {
            uint256 encoded;
            unchecked {
                encoded =
                    (obsCurrent.price0CumulativeLast - obsLast.price0CumulativeLast) /
                    uint32(obsCurrent.timestamp - obsLast.timestamp);
            }
            _basePerQuote = decode112with18(encoded);
        } else {
            uint256 encoded;
            unchecked {
                encoded =
                    (obsCurrent.price1CumulativeLast - obsLast.price1CumulativeLast) /
                    uint32(obsCurrent.timestamp - obsLast.timestamp);
            }
            _basePerQuote = decode112with18(encoded);
        }
    }

    // ====================================================================
    // Math Utilities
    // ====================================================================

    // Inspired by https://gist.github.com/alexroan/629172728f82cb5c88554896163b35a0#file-uniswapanchoredview-sol-L24
    // decode a uq112x112 into a uint with 18 decimals of precision
    function decode112with18(uint256 valToDecode) internal pure returns (uint256) {
        // we only have 256 - 224 = 32 bits to spare, so scaling up by ~60 bits is dangerous
        // instead, get close to:
        //  (x * 1e18) >> 112
        // without risk of overflowing, e.g.:
        //  (x) / 2 ** (112 - lg(1e18))
        return valToDecode / 5_192_296_858_534_827;
    }

    event NewTwapDurationSet(uint32 oldDuration, uint32 newDuration);

    error TokenNotInPair();
    error WrongDecimals();
    error PairNotOldEnough();
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

interface IDualOracle is IERC165 {
    function ORACLE_PRECISION() external view returns (uint256);

    function BASE_TOKEN_0() external view returns (address);

    function BASE_TOKEN_0_DECIMALS() external view returns (uint256);

    function BASE_TOKEN_1() external view returns (address);

    function BASE_TOKEN_1_DECIMALS() external view returns (uint256);

    function decimals() external view returns (uint8);

    function getPricesNormalized() external view returns (bool _isBadData, uint256 _priceLow, uint256 _priceHigh);

    function getPrices() external view returns (bool _isBadData, uint256 _priceLow, uint256 _priceHigh);

    function name() external view returns (string memory);

    function NORMALIZATION_0() external view returns (int256);

    function NORMALIZATION_1() external view returns (int256);

    function QUOTE_TOKEN_0() external view returns (address);

    function QUOTE_TOKEN_0_DECIMALS() external view returns (uint256);

    function QUOTE_TOKEN_1() external view returns (address);

    function QUOTE_TOKEN_1_DECIMALS() external view returns (uint256);
}

// SPDX-License-Identifier: GPL-2.0-or-later

pragma solidity >=0.7.6 <0.9.0;

import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';

/// @title Uniswap V3 Static Oracle
/// @notice Oracle contract for calculating price quoting against Uniswap V3
interface IStaticOracle {
  /// @notice Returns the address of the Uniswap V3 factory
  /// @dev This value is assigned during deployment and cannot be changed
  /// @return The address of the Uniswap V3 factory
  function UNISWAP_V3_FACTORY() external view returns (IUniswapV3Factory);

  /// @notice Returns how many observations are needed per minute in Uniswap V3 oracles, on the deployed chain
  /// @dev This value is assigned during deployment and cannot be changed
  /// @return Number of observation that are needed per minute
  function CARDINALITY_PER_MINUTE() external view returns (uint8);

  /// @notice Returns all supported fee tiers
  /// @return The supported fee tiers
  function supportedFeeTiers() external view returns (uint24[] memory);

  /// @notice Returns whether a specific pair can be supported by the oracle
  /// @dev The pair can be provided in tokenA/tokenB or tokenB/tokenA order
  /// @return Whether the given pair can be supported by the oracle
  function isPairSupported(address tokenA, address tokenB) external view returns (bool);

  /// @notice Returns all existing pools for the given pair
  /// @dev The pair can be provided in tokenA/tokenB or tokenB/tokenA order
  /// @return All existing pools for the given pair
  function getAllPoolsForPair(address tokenA, address tokenB) external view returns (address[] memory);

  /// @notice Returns a quote, based on the given tokens and amount, by querying all of the pair's pools
  /// @dev If some pools are not configured correctly for the given period, then they will be ignored
  /// @dev Will revert if there are no pools available/configured for the pair and period combination
  /// @param baseAmount Amount of token to be converted
  /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination
  /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination
  /// @param period Number of seconds from which to calculate the TWAP
  /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken
  /// @return queriedPools The pools that were queried to calculate the quote
  function quoteAllAvailablePoolsWithTimePeriod(
    uint128 baseAmount,
    address baseToken,
    address quoteToken,
    uint32 period
  ) external view returns (uint256 quoteAmount, address[] memory queriedPools);

  /// @notice Returns a quote, based on the given tokens and amount, by querying only the specified fee tiers
  /// @dev Will revert if the pair does not have a pool for one of the given fee tiers, or if one of the pools
  /// is not prepared/configured correctly for the given period
  /// @param baseAmount Amount of token to be converted
  /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination
  /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination
  /// @param feeTiers The fee tiers to consider when calculating the quote
  /// @param period Number of seconds from which to calculate the TWAP
  /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken
  /// @return queriedPools The pools that were queried to calculate the quote
  function quoteSpecificFeeTiersWithTimePeriod(
    uint128 baseAmount,
    address baseToken,
    address quoteToken,
    uint24[] calldata feeTiers,
    uint32 period
  ) external view returns (uint256 quoteAmount, address[] memory queriedPools);

  /// @notice Returns a quote, based on the given tokens and amount, by querying only the specified pools
  /// @dev Will revert if one of the pools is not prepared/configured correctly for the given period
  /// @param baseAmount Amount of token to be converted
  /// @param baseToken Address of an ERC20 token contract used as the baseAmount denomination
  /// @param quoteToken Address of an ERC20 token contract used as the quoteAmount denomination
  /// @param pools The pools to consider when calculating the quote
  /// @param period Number of seconds from which to calculate the TWAP
  /// @return quoteAmount Amount of quoteToken received for baseAmount of baseToken
  function quoteSpecificPoolsWithTimePeriod(
    uint128 baseAmount,
    address baseToken,
    address quoteToken,
    address[] calldata pools,
    uint32 period
  ) external view returns (uint256 quoteAmount);

  /// @notice Will initialize all existing pools for the given pair, so that they can be queried with the given period in the future
  /// @dev Will revert if there are no pools available for the pair and period combination
  /// @param tokenA One of the pair's tokens
  /// @param tokenB The other of the pair's tokens
  /// @param period The period that will be guaranteed when quoting
  /// @return preparedPools The pools that were prepared
  function prepareAllAvailablePoolsWithTimePeriod(
    address tokenA,
    address tokenB,
    uint32 period
  ) external returns (address[] memory preparedPools);

  /// @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
  /// @dev Will revert if the pair does not have a pool for a given fee tier
  /// @param tokenA One of the pair's tokens
  /// @param tokenB The other of the pair's tokens
  /// @param feeTiers The fee tiers to consider when searching for the pair's pools
  /// @param period The period that will be guaranteed when quoting
  /// @return preparedPools The pools that were prepared
  function prepareSpecificFeeTiersWithTimePeriod(
    address tokenA,
    address tokenB,
    uint24[] calldata feeTiers,
    uint32 period
  ) external returns (address[] memory preparedPools);

  /// @notice Will initialize all given pools, so that they can be queried with the given period in the future
  /// @param pools The pools to initialize
  /// @param period The period that will be guaranteed when quoting
  function prepareSpecificPoolsWithTimePeriod(address[] calldata pools, uint32 period) external;

  /// @notice Will increase observations for all existing pools for the given pair, so they start accruing information for twap calculations
  /// @dev Will revert if there are no pools available for the pair and period combination
  /// @param tokenA One of the pair's tokens
  /// @param tokenB The other of the pair's tokens
  /// @param cardinality The cardinality that will be guaranteed when quoting
  /// @return preparedPools The pools that were prepared
  function prepareAllAvailablePoolsWithCardinality(
    address tokenA,
    address tokenB,
    uint16 cardinality
  ) external returns (address[] memory preparedPools);

  /// @notice Will increase the pair's pools with the specified fee tiers observations, so they start accruing information for twap calculations
  /// @dev Will revert if the pair does not have a pool for a given fee tier
  /// @param tokenA One of the pair's tokens
  /// @param tokenB The other of the pair's tokens
  /// @param feeTiers The fee tiers to consider when searching for the pair's pools
  /// @param cardinality The cardinality that will be guaranteed when quoting
  /// @return preparedPools The pools that were prepared
  function prepareSpecificFeeTiersWithCardinality(
    address tokenA,
    address tokenB,
    uint24[] calldata feeTiers,
    uint16 cardinality
  ) external returns (address[] memory preparedPools);

  /// @notice Will increase all given pools observations, so they start accruing information for twap calculations
  /// @param pools The pools to initialize
  /// @param cardinality The cardinality that will be guaranteed when quoting
  function prepareSpecificPoolsWithCardinality(address[] calldata pools, uint16 cardinality) external;

  /// @notice Adds support for a new fee tier
  /// @dev Will revert if the given tier is invalid, or already supported
  /// @param feeTier The new fee tier to add
  function addNewFeeTier(uint24 feeTier) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Storage.sol)
pragma solidity ^0.8.0;

import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

/**
 * @dev Storage based implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165Storage is ERC165 {
    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return super.supportsInterface(interfaceId) || _supportedInterfaces[interfaceId];
    }

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;

import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

interface IUniswapV3SingleTwapOracle is IERC165 {
    event SetTwapDuration(uint256 oldTwapDuration, uint256 newTwapDuration);

    function TWAP_PRECISION() external view returns (uint128);

    function UNISWAP_V3_TWAP_BASE_TOKEN() external view returns (address);

    function UNISWAP_V3_TWAP_QUOTE_TOKEN() external view returns (address);

    function UNI_V3_PAIR_ADDRESS() external view returns (address);

    function getUniswapV3Twap() external view returns (uint256 _twap);

    function twapDuration() external view returns (uint32);

    function setTwapDuration(uint32 _newTwapDuration) external;
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorV3Interface {
  function decimals() external view returns (uint8);

  function description() external view returns (string memory);

  function version() external view returns (uint256);

  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;

import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

interface IChainlinkOracleWithMaxDelay is IERC165 {
    event SetMaximumOracleDelay(address oracle, uint256 oldMaxOracleDelay, uint256 newMaxOracleDelay);

    function CHAINLINK_FEED_ADDRESS() external view returns (address);

    function CHAINLINK_FEED_DECIMALS() external view returns (uint8);

    function CHAINLINK_FEED_PRECISION() external view returns (uint256);

    function getChainlinkPrice() external view returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth);

    function maximumOracleDelay() external view returns (uint256);

    function setMaximumOracleDelay(uint256 _newMaxOracleDelay) external;
}

// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;

import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

interface IEthUsdChainlinkOracleWithMaxDelay is IERC165 {
    event SetMaximumEthUsdOracleDelay(uint256 oldMaxOracleDelay, uint256 newMaxOracleDelay);

    function ETH_USD_CHAINLINK_FEED_ADDRESS() external view returns (address);

    function ETH_USD_CHAINLINK_FEED_DECIMALS() external view returns (uint8);

    function ETH_USD_CHAINLINK_FEED_PRECISION() external view returns (uint256);

    function maximumEthUsdOracleDelay() external view returns (uint256);

    function getEthUsdChainlinkPrice() external view returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth);

    function setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import { IUniswapV2Pair } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol";

/// @dev Fraxswap LP Pair Interface
interface IFraxswapPair is IUniswapV2Pair {
    // TWAMM
    struct TWAPObservation {
        uint256 timestamp;
        uint256 price0CumulativeLast;
        uint256 price1CumulativeLast;
    }

    function TWAPObservationHistory(uint256 index) external view returns (TWAPObservation memory);

    event LongTermSwap0To1(address indexed addr, uint256 orderId, uint256 amount0In, uint256 numberOfTimeIntervals);
    event LongTermSwap1To0(address indexed addr, uint256 orderId, uint256 amount1In, uint256 numberOfTimeIntervals);
    event CancelLongTermOrder(
        address indexed addr,
        uint256 orderId,
        address sellToken,
        uint256 unsoldAmount,
        address buyToken,
        uint256 purchasedAmount
    );
    event WithdrawProceedsFromLongTermOrder(
        address indexed addr,
        uint256 orderId,
        address indexed proceedToken,
        uint256 proceeds,
        bool orderExpired
    );

    function fee() external view returns (uint256);

    function longTermSwapFrom0To1(uint256 amount0In, uint256 numberOfTimeIntervals) external returns (uint256 orderId);
    function longTermSwapFrom1To0(uint256 amount1In, uint256 numberOfTimeIntervals) external returns (uint256 orderId);
    function cancelLongTermSwap(uint256 orderId) external;
    function withdrawProceedsFromLongTermSwap(
        uint256 orderId
    ) external returns (bool is_expired, address rewardTkn, uint256 totalReward);
    function executeVirtualOrders(uint256 blockTimestamp) external;

    function getAmountOut(uint256 amountIn, address tokenIn) external view returns (uint256);
    function getAmountIn(uint256 amountOut, address tokenOut) external view returns (uint256);

    function orderTimeInterval() external returns (uint256);
    function getTWAPHistoryLength() external view returns (uint256);
    function getTwammReserves()
        external
        view
        returns (
            uint112 _reserve0,
            uint112 _reserve1,
            uint32 _blockTimestampLast,
            uint112 _twammReserve0,
            uint112 _twammReserve1,
            uint256 _fee
        );
    function getReserveAfterTwamm(
        uint256 blockTimestamp
    )
        external
        view
        returns (
            uint112 _reserve0,
            uint112 _reserve1,
            uint256 lastVirtualOrderTimestamp,
            uint112 _twammReserve0,
            uint112 _twammReserve1
        );
    function getNextOrderID() external view returns (uint256);
    function getOrderIDsForUser(address user) external view returns (uint256[] memory);
    function getOrderIDsForUserLength(address user) external view returns (uint256);
    function twammUpToDate() external view returns (bool);
    function getTwammState()
        external
        view
        returns (
            uint256 token0Rate,
            uint256 token1Rate,
            uint256 lastVirtualOrderTimestamp,
            uint256 orderTimeInterval_rtn,
            uint256 rewardFactorPool0,
            uint256 rewardFactorPool1
        );
    function getTwammSalesRateEnding(
        uint256 _blockTimestamp
    ) external view returns (uint256 orderPool0SalesRateEnding, uint256 orderPool1SalesRateEnding);
    function getTwammRewardFactor(
        uint256 _blockTimestamp
    ) external view returns (uint256 rewardFactorPool0AtTimestamp, uint256 rewardFactorPool1AtTimestamp);
    function getTwammOrder(
        uint256 orderId
    )
        external
        view
        returns (
            uint256 id,
            uint256 creationTimestamp,
            uint256 expirationTimestamp,
            uint256 saleRate,
            address owner,
            address sellTokenAddr,
            address buyTokenAddr
        );
    function getTwammOrderProceedsView(
        uint256 orderId,
        uint256 blockTimestamp
    ) external view returns (bool orderExpired, uint256 totalReward);
    function getTwammOrderProceeds(uint256 orderId) external returns (bool orderExpired, uint256 totalReward);

    function togglePauseNewSwaps() external;
}

// SPDX-License-Identifier: ISC
pragma solidity >=0.8.0;
// File contracts/Fraxswap/core/libraries/UQ112x112.sol

// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))

// range: [0, 2**112 - 1]
// resolution: 1 / 2**112

library UQ112x112 {
    uint224 constant Q112 = 2 ** 112;

    // encode a uint112 as a UQ112x112
    function encode(uint112 y) internal pure returns (uint224 z) {
        z = uint224(y) * Q112; // never overflows
    }

    // divide a UQ112x112 by a uint112, returning a UQ112x112
    function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
        z = x / uint224(y);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

/// @title The interface for the Uniswap V3 Factory
/// @notice The Uniswap V3 Factory facilitates creation of Uniswap V3 pools and control over the protocol fees
interface IUniswapV3Factory {
    /// @notice Emitted when the owner of the factory is changed
    /// @param oldOwner The owner before the owner was changed
    /// @param newOwner The owner after the owner was changed
    event OwnerChanged(address indexed oldOwner, address indexed newOwner);

    /// @notice Emitted when a pool is created
    /// @param token0 The first token of the pool by address sort order
    /// @param token1 The second token of the pool by address sort order
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
    /// @param tickSpacing The minimum number of ticks between initialized ticks
    /// @param pool The address of the created pool
    event PoolCreated(
        address indexed token0,
        address indexed token1,
        uint24 indexed fee,
        int24 tickSpacing,
        address pool
    );

    /// @notice Emitted when a new fee amount is enabled for pool creation via the factory
    /// @param fee The enabled fee, denominated in hundredths of a bip
    /// @param tickSpacing The minimum number of ticks between initialized ticks for pools created with the given fee
    event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);

    /// @notice Returns the current owner of the factory
    /// @dev Can be changed by the current owner via setOwner
    /// @return The address of the factory owner
    function owner() external view returns (address);

    /// @notice Returns the tick spacing for a given fee amount, if enabled, or 0 if not enabled
    /// @dev A fee amount can never be removed, so this value should be hard coded or cached in the calling context
    /// @param fee The enabled fee, denominated in hundredths of a bip. Returns 0 in case of unenabled fee
    /// @return The tick spacing
    function feeAmountTickSpacing(uint24 fee) external view returns (int24);

    /// @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
    /// @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
    /// @param tokenA The contract address of either token0 or token1
    /// @param tokenB The contract address of the other token
    /// @param fee The fee collected upon every swap in the pool, denominated in hundredths of a bip
    /// @return pool The pool address
    function getPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external view returns (address pool);

    /// @notice Creates a pool for the given two tokens and fee
    /// @param tokenA One of the two tokens in the desired pool
    /// @param tokenB The other of the two tokens in the desired pool
    /// @param fee The desired fee for the pool
    /// @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved
    /// from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments
    /// are invalid.
    /// @return pool The address of the newly created pool
    function createPool(
        address tokenA,
        address tokenB,
        uint24 fee
    ) external returns (address pool);

    /// @notice Updates the owner of the factory
    /// @dev Must be called by the current owner
    /// @param _owner The new owner of the factory
    function setOwner(address _owner) external;

    /// @notice Enables a fee amount with the given tickSpacing
    /// @dev Fee amounts may never be removed once enabled
    /// @param fee The fee amount to enable, denominated in hundredths of a bip (i.e. 1e-6)
    /// @param tickSpacing The spacing between ticks to be enforced for all pools created with the given fee amount
    function enableFeeAmount(uint24 fee, int24 tickSpacing) external;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}

pragma solidity >=0.5.0;

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function kLast() external view returns (uint);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

    function initialize(address, address) external;
}

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/",
    "@mean-finance/=node_modules/@mean-finance/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "@rari-capital/=node_modules/@rari-capital/",
    "@uniswap/=node_modules/@uniswap/",
    "dev-fraxswap/=node_modules/dev-fraxswap/",
    "frax-standard-solidity/=node_modules/frax-standard-solidity/",
    "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": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"components":[{"internalType":"address","name":"fraxswapPair","type":"address"},{"internalType":"uint32","name":"twapDuration","type":"uint32"},{"internalType":"address","name":"frxEthErc20","type":"address"},{"internalType":"address","name":"frxEthUsdChainlinkFeed","type":"address"},{"internalType":"uint256","name":"maximumOracleDelay","type":"uint256"},{"internalType":"address","name":"timelockAddress","type":"address"}],"internalType":"struct ConstructorParams","name":"_params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"OnlyPendingTimelock","type":"error"},{"inputs":[],"name":"OnlyTimelock","type":"error"},{"inputs":[],"name":"PairNotOldEnough","type":"error"},{"inputs":[],"name":"TokenNotInPair","type":"error"},{"inputs":[],"name":"WrongDecimals","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"oldDuration","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"newDuration","type":"uint32"}],"name":"NewTwapDurationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMaxOracleDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxOracleDelay","type":"uint256"}],"name":"SetMaximumEthUsdOracleDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockTransferred","type":"event"},{"inputs":[],"name":"BASE_TOKEN_0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_TOKEN_0_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_TOKEN_1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BASE_TOKEN_1_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_USD_CHAINLINK_FEED_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_USD_CHAINLINK_FEED_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_USD_CHAINLINK_FEED_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRAXSWAP_BASE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRAXSWAP_PAIR","outputs":[{"internalType":"contract IFraxswapPair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRAXSWAP_QUOTE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRXETH_ERC20","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NORMALIZATION_0","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NORMALIZATION_1","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ORACLE_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_TOKEN_0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_TOKEN_0_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_TOKEN_1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE_TOKEN_1_DECIMALS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_getTwapFraxSwapPair","outputs":[{"internalType":"uint256","name":"_basePerQuote","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptTransferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getEthPerUsdRedStone","outputs":[{"internalType":"bool","name":"_isBadData","type":"bool"},{"internalType":"uint256","name":"_ethPerUsd","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEthUsdChainlinkPrice","outputs":[{"internalType":"bool","name":"_isBadData","type":"bool"},{"internalType":"uint256","name":"_updatedAt","type":"uint256"},{"internalType":"uint256","name":"_usdPerEth","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrices","outputs":[{"internalType":"bool","name":"_isBadData","type":"bool"},{"internalType":"uint256","name":"_priceLow","type":"uint256"},{"internalType":"uint256","name":"_priceHigh","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPricesNormalized","outputs":[{"internalType":"bool","name":"_isBadDataNormal","type":"bool"},{"internalType":"uint256","name":"_priceLowNormal","type":"uint256"},{"internalType":"uint256","name":"_priceHighNormal","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumEthUsdOracleDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"pendingTimelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newMaxOracleDelay","type":"uint256"}],"name":"setMaximumEthUsdOracleDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_newTwapDuration","type":"uint32"}],"name":"setTwapDurationFraxSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newTimelock","type":"address"}],"name":"transferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twapDuration","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"}]

61026060405234801562000011575f80fd5b506040516200236b3803806200236b8339810160408190526200003491620006c8565b6040805180820182526060808401516001600160a01b0390811683526080808601516020808601919091528551808501875287518416815287870180518516828401528289015163ffffffff168289015287516101008082018a526103488083526012958301868152845189169b84018c905298830186815283880191825260a080850188815295518a1660c080870191825260e08088019a8b529e909a52915160ff9081169182905291518a1690985295518616909a528151871690529551831661012081905297519094166101405292511661016052929390926200011c919062000789565b610180526101605160e05162000133919062000789565b6101a05250600180546001600160a01b0319163317905580516001600160a01b03166101c08190526040808301516004805463ffffffff909216600160a01b0263ffffffff60a01b199092169190911781558151630dfe168160e01b815291515f9392630dfe168192818101926020929091908290030181865afa158015620001be573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001e49190620007b2565b90505f6101c0516001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000227573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200024d9190620007b2565b905082602001516001600160a01b0316826001600160a01b031603620002bb57600480546020850151600160c01b600164ff0000000160a01b03199092166001600160a01b039182161791909117909155600380546001600160a01b0319169183169190911790556200032c565b82602001516001600160a01b0316816001600160a01b03160362000313576020830151600480546001600160a01b03199081166001600160a01b0393841617909155600380549091169184169190911790556200032c565b604051630c40208b60e01b815260040160405180910390fd5b60056101c0516001600160a01b0316637fa2ee6e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200036e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620003949190620007d5565b1015620003b4576040516355c21b8960e11b815260040160405180910390fd5b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003f1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620004179190620007ed565b60ff166012146200043b57604051632754761960e01b815260040160405180910390fd5b806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000478573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200049e9190620007ed565b60ff16601214620004c257604051632754761960e01b815260040160405180910390fd5b505050620004dd6323e2f2e160e11b620005ba60201b60201c565b80516001600160a01b03166101e08190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa15801562000528573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200054e9190620007ed565b60ff166102008190526200056490600a6200090a565b610220526020015160055560a08101516200057f906200063d565b6200059163415f130360e01b620005ba565b620005a3632fa3fc3160e21b620005ba565b604001516001600160a01b03166102405262000917565b6001600160e01b03198082169003620006195760405162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015260640160405180910390fd5b6001600160e01b0319165f908152600260205260409020805460ff19166001179055565b6001546040516001600160a01b038084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b80516001600160a01b0381168114620006af575f80fd5b919050565b805163ffffffff81168114620006af575f80fd5b5f60c08284031215620006d9575f80fd5b60405160c081016001600160401b03811182821017156200070857634e487b7160e01b5f52604160045260245ffd5b604052620007168362000698565b81526200072660208401620006b4565b6020820152620007396040840162000698565b60408201526200074c6060840162000698565b6060820152608083015160808201526200076960a0840162000698565b60a08201529392505050565b634e487b7160e01b5f52601160045260245ffd5b8181035f831280158383131683831282161715620007ab57620007ab62000775565b5092915050565b5f60208284031215620007c3575f80fd5b620007ce8262000698565b9392505050565b5f60208284031215620007e6575f80fd5b5051919050565b5f60208284031215620007fe575f80fd5b815160ff81168114620007ce575f80fd5b600181815b808511156200084f57815f190482111562000833576200083362000775565b808516156200084157918102915b93841c939080029062000814565b509250929050565b5f82620008675750600162000904565b816200087557505f62000904565b81600181146200088e57600281146200089957620008b9565b600191505062000904565b60ff841115620008ad57620008ad62000775565b50506001821b62000904565b5060208310610133831016604e8410600b8410161715620008de575081810a62000904565b620008ea83836200080f565b805f190482111562000900576200090062000775565b0290505b92915050565b5f620007ce838362000857565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161195762000a145f395f61054301525f81816104cc0152610efb01525f6103cf01525f818161056a015261107001525f81816105a001528181610757015281816107fc0152818161089a01528181610a900152610bca01525f818161023d01528181610e1101528181610e3a0152610e7d01525f81816105cf01528181610d7001528181610d990152610ddc01525f6103a801525f61032f01525f61065701525f61030801525f6104f301525f61048501525f61063001525f61060901526119575ff3fe608060405234801561000f575f80fd5b5060043610610234575f3560e01c8063550af47e1161013d5780639c0d313f116100b8578063d736094611610088578063e5a66dfa1161006e578063e5a66dfa1461062b578063f097486c14610652578063f6ccaad414610679575f80fd5b8063d7360946146105f1578063e0d2e78014610604575f80fd5b80639c0d313f1461058c5780639f50f7611461059b578063bd9a548b146105c2578063c82f2b12146105ca575f80fd5b8063781097d01161010d57806388c210f7116100f357806388c210f71461051e57806390e67fe81461053e57806399a64f2814610565575f80fd5b8063781097d0146104ee5780637c99a49914610515575f80fd5b8063550af47e1461046157806359c909e1146104805780635f9a63e4146104a7578063726de1a5146104c7575f80fd5b8063313ce567116101cd57806343aae02d1161019d5780634bc66f32116101835780634bc66f32146104315780634d3375e8146104515780634f8b4ae714610459575f80fd5b806343aae02d14610416578063450140951461041e575f80fd5b8063313ce5671461038e57806337f85f66146103a35780633b17136a146103ca5780633cb6f5fa146103f1575f80fd5b8063090f3f5011610208578063090f3f50146102bf578063116d797614610303578063208880041461032a57806326d8954514610351575f80fd5b806232e91a1461023857806301ffc9a71461027257806306fdde0314610295578063075a194e146102aa575b5f80fd5b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6102856102803660046113b1565b610681565b6040519015158152602001610269565b61029d610708565b60405161026991906113f0565b6102bd6102b836600461146a565b610728565b005b5f546102de9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610269565b6102de7f000000000000000000000000000000000000000000000000000000000000000081565b6102de7f000000000000000000000000000000000000000000000000000000000000000081565b6004546103799074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610269565b60125b60405160ff9091168152602001610269565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6103917f000000000000000000000000000000000000000000000000000000000000000081565b6103f961073c565b604080519315158452602084019290925290820152606001610269565b61025f610753565b6102bd61042c366004611485565b610d45565b6001546102de9073ffffffffffffffffffffffffffffffffffffffff1681565b6103f9610d56565b6102bd610eb7565b610469610edb565b604080519215158352602083019190915201610269565b6102de7f000000000000000000000000000000000000000000000000000000000000000081565b6003546102de9073ffffffffffffffffffffffffffffffffffffffff1681565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f60055481565b6004546102de9073ffffffffffffffffffffffffffffffffffffffff1681565b6102de7f000000000000000000000000000000000000000000000000000000000000000081565b6102de7f000000000000000000000000000000000000000000000000000000000000000081565b61025f670de0b6b3a764000081565b6102de7f000000000000000000000000000000000000000000000000000000000000000081565b6103f9610f36565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6102bd6105ff3660046114b8565b610f4c565b6102de7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6102bd610f5d565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061070257507fffffffff0000000000000000000000000000000000000000000000000000000082165f9081526002602052604090205460ff165b92915050565b606060405180606001604052806022815260200161192960229139905090565b610730610f6d565b61073981610fbe565b50565b5f805f610747611069565b91959094509092509050565b5f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637fa2ee6e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107e291906114cf565b90505f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166327e7383661082c600185611513565b6040518263ffffffff1660e01b815260040161084a91815260200190565b606060405180830381865afa158015610865573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108899190611526565b905042815f015110156109f6575f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015610901573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061092591906115c7565b5090925090505f61093b64010000000042611638565b8451909150810363ffffffff811661097a8561095686611126565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690611150565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16028560200181815101915081815250508063ffffffff166109bc8461095687611126565b6040870180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216929092020190525063ffffffff16835250505b610a1760405180606001604052805f81526020015f81526020015f81525090565b6004545f908190610a489060289074010000000000000000000000000000000000000000900463ffffffff1661164b565b63ffffffff1690505b60045474010000000000000000000000000000000000000000900463ffffffff16811015610ba95773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166327e73836610ac083600161166d565b610aca9088611513565b6040518263ffffffff1660e01b8152600401610ae891815260200190565b606060405180830381865afa158015610b03573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b279190611526565b600454815186519295507401000000000000000000000000000000000000000090910463ffffffff1691031015610b6057809150610b65565b610ba9565b600454610b929060149074010000000000000000000000000000000000000000900463ffffffff1661164b565b610ba29063ffffffff168261166d565b9050610a51565b505b83811015610ca35773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166327e73836610bfa83600161166d565b610c049087611513565b6040518263ffffffff1660e01b8152600401610c2291815260200190565b606060405180830381865afa158015610c3d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c619190611526565b600454815185519294507401000000000000000000000000000000000000000090910463ffffffff16910311610ca35780610c9b81611680565b915050610bab565b6004547801000000000000000000000000000000000000000000000000900460ff1615610d06575f825f0151845f01510363ffffffff16836020015185602001510381610cf257610cf261160b565b049050610cfe81611172565b955050610d3e565b5f825f0151845f01510363ffffffff16836040015185604001510381610d2e57610d2e61160b565b049050610d3a81611172565b9550505b5050505090565b610d4d610f6d565b61073981611184565b5f805f805f80610d646111f8565b9250925092508295505f7f000000000000000000000000000000000000000000000000000000000000000013610dd757610dbd7f00000000000000000000000000000000000000000000000000000000000000006116b7565b610dc890600a61180b565b610dd29083611816565b610e0c565b610e027f0000000000000000000000000000000000000000000000000000000000000000600a61180b565b610e0c9083611829565b94505f7f000000000000000000000000000000000000000000000000000000000000000013610e7857610e5e7f00000000000000000000000000000000000000000000000000000000000000006116b7565b610e6990600a61180b565b610e739082611816565b610ead565b610ea37f0000000000000000000000000000000000000000000000000000000000000000600a61180b565b610ead9082611829565b9350505050909192565b610ebf610f6d565b610ec7611263565b610ed05f611184565b610ed95f6112b3565b565b5f805f80610ee7611069565b925050915081935080670de0b6b3a76400007f0000000000000000000000000000000000000000000000000000000000000000610f249190611829565b610f2e9190611816565b925050509091565b5f805f610f416111f8565b925092509250909192565b610f54610f6d565b61073981611340565b610f65611263565b610ed9611381565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ed9576040517f1c0be90a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546040805163ffffffff740100000000000000000000000000000000000000009093048316815291831660208301527fe99a18add462219d56cbe6eacbd37b6795ea7beb885a903238a2fe939b6dfa24910160405180910390a16004805463ffffffff90921674010000000000000000000000000000000000000000027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b5f805f805f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156110d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110fb9190611859565b509350509250505f8213158061111b57506005546111198242611513565b115b959094509092509050565b5f6107026e0100000000000000000000000000006dffffffffffffffffffffffffffff84166118a5565b5f61116b6dffffffffffffffffffffffffffff8316846118ec565b9392505050565b5f6107026612725dd1d243ab83611816565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a9190a350565b5f805f805f611205610edb565b915091505f611212610753565b90505f816112296002670de0b6b3a764000061191a565b6112339190611816565b90508396508281106112455782611247565b805b95508083116112565780611258565b825b945050505050909192565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610ed9576040517ff5c49e6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60055460408051918252602082018390527f1b427db70b2e813aae1e9f4dc54fcd2ae904b1350f60b84a7bab7d379aa2b02e910160405180910390a1600555565b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610ed9336112b3565b5f602082840312156113c1575f80fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461116b575f80fd5b5f6020808352835180828501525f5b8181101561141b578581018301518582016040015282016113ff565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b63ffffffff81168114610739575f80fd5b5f6020828403121561147a575f80fd5b813561116b81611459565b5f60208284031215611495575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461116b575f80fd5b5f602082840312156114c8575f80fd5b5035919050565b5f602082840312156114df575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610702576107026114e6565b5f60608284031215611536575f80fd5b6040516060810181811067ffffffffffffffff8211171561157e577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b80604052508251815260208301516020820152604083015160408201528091505092915050565b80516dffffffffffffffffffffffffffff811681146115c2575f80fd5b919050565b5f805f606084860312156115d9575f80fd5b6115e2846115a5565b92506115f0602085016115a5565b9150604084015161160081611459565b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826116465761164661160b565b500690565b5f63ffffffff808416806116615761166161160b565b92169190910492915050565b80820180821115610702576107026114e6565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036116b0576116b06114e6565b5060010190565b5f7f800000000000000000000000000000000000000000000000000000000000000082036116e7576116e76114e6565b505f0390565b600181815b8085111561174657817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561172c5761172c6114e6565b8085161561173957918102915b93841c93908002906116f2565b509250929050565b5f8261175c57506001610702565b8161176857505f610702565b816001811461177e5760028114611788576117a4565b6001915050610702565b60ff841115611799576117996114e6565b50506001821b610702565b5060208310610133831016604e8410600b84101617156117c7575081810a610702565b6117d183836116ed565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611803576118036114e6565b029392505050565b5f61116b838361174e565b5f826118245761182461160b565b500490565b8082028115828204841417610702576107026114e6565b805169ffffffffffffffffffff811681146115c2575f80fd5b5f805f805f60a0868803121561186d575f80fd5b61187686611840565b945060208601519350604086015192506060860151915061189960808701611840565b90509295509295909350565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8281168282168181028316929181158285048214176118e3576118e36114e6565b50505092915050565b5f7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff808416806116615761166161160b565b5f61116b60ff84168361174e56fe4672784574682052656453746f6e65204475616c204f7261636c65202b2054574150a164736f6c6343000814000a0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff90000000000000000000000000000000000000000000000000000000000000f3c000000000000000000000000fc0000000000000000000000000000000000000600000000000000000000000089e60b56efd70a1d4fbbae947bc33cae41e37a720000000000000000000000000000000000000000000000000000000000000f3c000000000000000000000000c16068d1ca7e24e20e56bb70af4d00d92aa4f0b2

Deployed Bytecode

0x608060405234801561000f575f80fd5b5060043610610234575f3560e01c8063550af47e1161013d5780639c0d313f116100b8578063d736094611610088578063e5a66dfa1161006e578063e5a66dfa1461062b578063f097486c14610652578063f6ccaad414610679575f80fd5b8063d7360946146105f1578063e0d2e78014610604575f80fd5b80639c0d313f1461058c5780639f50f7611461059b578063bd9a548b146105c2578063c82f2b12146105ca575f80fd5b8063781097d01161010d57806388c210f7116100f357806388c210f71461051e57806390e67fe81461053e57806399a64f2814610565575f80fd5b8063781097d0146104ee5780637c99a49914610515575f80fd5b8063550af47e1461046157806359c909e1146104805780635f9a63e4146104a7578063726de1a5146104c7575f80fd5b8063313ce567116101cd57806343aae02d1161019d5780634bc66f32116101835780634bc66f32146104315780634d3375e8146104515780634f8b4ae714610459575f80fd5b806343aae02d14610416578063450140951461041e575f80fd5b8063313ce5671461038e57806337f85f66146103a35780633b17136a146103ca5780633cb6f5fa146103f1575f80fd5b8063090f3f5011610208578063090f3f50146102bf578063116d797614610303578063208880041461032a57806326d8954514610351575f80fd5b806232e91a1461023857806301ffc9a71461027257806306fdde0314610295578063075a194e146102aa575b5f80fd5b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6102856102803660046113b1565b610681565b6040519015158152602001610269565b61029d610708565b60405161026991906113f0565b6102bd6102b836600461146a565b610728565b005b5f546102de9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610269565b6102de7f000000000000000000000000000000000000000000000000000000000000034881565b6102de7f000000000000000000000000000000000000000000000000000000000000034881565b6004546103799074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610269565b60125b60405160ff9091168152602001610269565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b6103917f000000000000000000000000000000000000000000000000000000000000000881565b6103f961073c565b604080519315158452602084019290925290820152606001610269565b61025f610753565b6102bd61042c366004611485565b610d45565b6001546102de9073ffffffffffffffffffffffffffffffffffffffff1681565b6103f9610d56565b6102bd610eb7565b610469610edb565b604080519215158352602083019190915201610269565b6102de7f000000000000000000000000fc0000000000000000000000000000000000000681565b6003546102de9073ffffffffffffffffffffffffffffffffffffffff1681565b61025f7f0000000000000000000000000000000000000000000000000000000005f5e10081565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b61025f60055481565b6004546102de9073ffffffffffffffffffffffffffffffffffffffff1681565b6102de7f000000000000000000000000fc0000000000000000000000000000000000000681565b6102de7f00000000000000000000000089e60b56efd70a1d4fbbae947bc33cae41e37a7281565b61025f670de0b6b3a764000081565b6102de7f0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff981565b6103f9610f36565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6102bd6105ff3660046114b8565b610f4c565b6102de7f000000000000000000000000fc0000000000000000000000000000000000000681565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b6102bd610f5d565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061070257507fffffffff0000000000000000000000000000000000000000000000000000000082165f9081526002602052604090205460ff165b92915050565b606060405180606001604052806022815260200161192960229139905090565b610730610f6d565b61073981610fbe565b50565b5f805f610747611069565b91959094509092509050565b5f807f0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff973ffffffffffffffffffffffffffffffffffffffff16637fa2ee6e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107e291906114cf565b90505f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff9166327e7383661082c600185611513565b6040518263ffffffff1660e01b815260040161084a91815260200190565b606060405180830381865afa158015610865573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108899190611526565b905042815f015110156109f6575f807f0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff973ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015610901573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061092591906115c7565b5090925090505f61093b64010000000042611638565b8451909150810363ffffffff811661097a8561095686611126565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690611150565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16028560200181815101915081815250508063ffffffff166109bc8461095687611126565b6040870180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216929092020190525063ffffffff16835250505b610a1760405180606001604052805f81526020015f81526020015f81525090565b6004545f908190610a489060289074010000000000000000000000000000000000000000900463ffffffff1661164b565b63ffffffff1690505b60045474010000000000000000000000000000000000000000900463ffffffff16811015610ba95773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff9166327e73836610ac083600161166d565b610aca9088611513565b6040518263ffffffff1660e01b8152600401610ae891815260200190565b606060405180830381865afa158015610b03573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b279190611526565b600454815186519295507401000000000000000000000000000000000000000090910463ffffffff1691031015610b6057809150610b65565b610ba9565b600454610b929060149074010000000000000000000000000000000000000000900463ffffffff1661164b565b610ba29063ffffffff168261166d565b9050610a51565b505b83811015610ca35773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff9166327e73836610bfa83600161166d565b610c049087611513565b6040518263ffffffff1660e01b8152600401610c2291815260200190565b606060405180830381865afa158015610c3d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c619190611526565b600454815185519294507401000000000000000000000000000000000000000090910463ffffffff16910311610ca35780610c9b81611680565b915050610bab565b6004547801000000000000000000000000000000000000000000000000900460ff1615610d06575f825f0151845f01510363ffffffff16836020015185602001510381610cf257610cf261160b565b049050610cfe81611172565b955050610d3e565b5f825f0151845f01510363ffffffff16836040015185604001510381610d2e57610d2e61160b565b049050610d3a81611172565b9550505b5050505090565b610d4d610f6d565b61073981611184565b5f805f805f80610d646111f8565b9250925092508295505f7f000000000000000000000000000000000000000000000000000000000000000013610dd757610dbd7f00000000000000000000000000000000000000000000000000000000000000006116b7565b610dc890600a61180b565b610dd29083611816565b610e0c565b610e027f0000000000000000000000000000000000000000000000000000000000000000600a61180b565b610e0c9083611829565b94505f7f000000000000000000000000000000000000000000000000000000000000000013610e7857610e5e7f00000000000000000000000000000000000000000000000000000000000000006116b7565b610e6990600a61180b565b610e739082611816565b610ead565b610ea37f0000000000000000000000000000000000000000000000000000000000000000600a61180b565b610ead9082611829565b9350505050909192565b610ebf610f6d565b610ec7611263565b610ed05f611184565b610ed95f6112b3565b565b5f805f80610ee7611069565b925050915081935080670de0b6b3a76400007f0000000000000000000000000000000000000000000000000000000005f5e100610f249190611829565b610f2e9190611816565b925050509091565b5f805f610f416111f8565b925092509250909192565b610f54610f6d565b61073981611340565b610f65611263565b610ed9611381565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ed9576040517f1c0be90a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546040805163ffffffff740100000000000000000000000000000000000000009093048316815291831660208301527fe99a18add462219d56cbe6eacbd37b6795ea7beb885a903238a2fe939b6dfa24910160405180910390a16004805463ffffffff90921674010000000000000000000000000000000000000000027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b5f805f805f7f00000000000000000000000089e60b56efd70a1d4fbbae947bc33cae41e37a7273ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156110d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110fb9190611859565b509350509250505f8213158061111b57506005546111198242611513565b115b959094509092509050565b5f6107026e0100000000000000000000000000006dffffffffffffffffffffffffffff84166118a5565b5f61116b6dffffffffffffffffffffffffffff8316846118ec565b9392505050565b5f6107026612725dd1d243ab83611816565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a9190a350565b5f805f805f611205610edb565b915091505f611212610753565b90505f816112296002670de0b6b3a764000061191a565b6112339190611816565b90508396508281106112455782611247565b805b95508083116112565780611258565b825b945050505050909192565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610ed9576040517ff5c49e6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60055460408051918252602082018390527f1b427db70b2e813aae1e9f4dc54fcd2ae904b1350f60b84a7bab7d379aa2b02e910160405180910390a1600555565b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610ed9336112b3565b5f602082840312156113c1575f80fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461116b575f80fd5b5f6020808352835180828501525f5b8181101561141b578581018301518582016040015282016113ff565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b63ffffffff81168114610739575f80fd5b5f6020828403121561147a575f80fd5b813561116b81611459565b5f60208284031215611495575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff8116811461116b575f80fd5b5f602082840312156114c8575f80fd5b5035919050565b5f602082840312156114df575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610702576107026114e6565b5f60608284031215611536575f80fd5b6040516060810181811067ffffffffffffffff8211171561157e577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b80604052508251815260208301516020820152604083015160408201528091505092915050565b80516dffffffffffffffffffffffffffff811681146115c2575f80fd5b919050565b5f805f606084860312156115d9575f80fd5b6115e2846115a5565b92506115f0602085016115a5565b9150604084015161160081611459565b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f826116465761164661160b565b500690565b5f63ffffffff808416806116615761166161160b565b92169190910492915050565b80820180821115610702576107026114e6565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036116b0576116b06114e6565b5060010190565b5f7f800000000000000000000000000000000000000000000000000000000000000082036116e7576116e76114e6565b505f0390565b600181815b8085111561174657817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561172c5761172c6114e6565b8085161561173957918102915b93841c93908002906116f2565b509250929050565b5f8261175c57506001610702565b8161176857505f610702565b816001811461177e5760028114611788576117a4565b6001915050610702565b60ff841115611799576117996114e6565b50506001821b610702565b5060208310610133831016604e8410600b84101617156117c7575081810a610702565b6117d183836116ed565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611803576118036114e6565b029392505050565b5f61116b838361174e565b5f826118245761182461160b565b500490565b8082028115828204841417610702576107026114e6565b805169ffffffffffffffffffff811681146115c2575f80fd5b5f805f805f60a0868803121561186d575f80fd5b61187686611840565b945060208601519350604086015192506060860151915061189960808701611840565b90509295509295909350565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8281168282168181028316929181158285048214176118e3576118e36114e6565b50505092915050565b5f7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff808416806116615761166161160b565b5f61116b60ff84168361174e56fe4672784574682052656453746f6e65204475616c204f7261636c65202b2054574150a164736f6c6343000814000a

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff90000000000000000000000000000000000000000000000000000000000000f3c000000000000000000000000fc0000000000000000000000000000000000000600000000000000000000000089e60b56efd70a1d4fbbae947bc33cae41e37a720000000000000000000000000000000000000000000000000000000000000f3c000000000000000000000000c16068d1ca7e24e20e56bb70af4d00d92aa4f0b2

-----Decoded View---------------
Arg [0] : _params (tuple):
Arg [1] : fraxswapPair (address): 0x4527bcEd9d41706D1436507e9a6e354d3FF44ff9
Arg [2] : twapDuration (uint32): 3900
Arg [3] : frxEthErc20 (address): 0xFC00000000000000000000000000000000000006
Arg [4] : frxEthUsdChainlinkFeed (address): 0x89e60b56efD70a1D4FBBaE947bC33cae41e37A72
Arg [5] : maximumOracleDelay (uint256): 3900
Arg [6] : timelockAddress (address): 0xc16068d1ca7E24E20e56bB70af4D00D92AA4f0b2


-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 0000000000000000000000004527bced9d41706d1436507e9a6e354d3ff44ff9
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000f3c
Arg [2] : 000000000000000000000000fc00000000000000000000000000000000000006
Arg [3] : 00000000000000000000000089e60b56efd70a1d4fbbae947bc33cae41e37a72
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000f3c
Arg [5] : 000000000000000000000000c16068d1ca7e24e20e56bb70af4d00d92aa4f0b2


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.