FRAX Price: $0.85 (-15.78%)

Contract

0xB99c9d329Bd69dDf8AF57110e011F5D81801c6d2

Overview

FRAX Balance | FXTL Balance

0 FRAX | 11,431 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
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
312730752026-01-25 16:01:0110 mins ago1769356861
0xB99c9d32...81801c6d2
0 FRAX
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FxsDualOracle

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;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ========================== FxsDualOracle ===========================
// ====================================================================
// 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 { ChainlinkOracleWithMaxDelay, ConstructorParams as ChainlinkOracleWithMaxDelayParams } from "../abstracts/ChainlinkOracleWithMaxDelay.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 fxsErc20;
    address fxsRedstoneFeed;
    uint256 maximumOracleDelay;
    address timelockAddress;
}

/// @title FrxEthDualOracle
contract FxsDualOracle is DualOracleBase, Timelock2Step, FraxSwapTwapOracle, ChainlinkOracleWithMaxDelay {
    address public immutable FXS_ERC20;

    constructor(
        ConstructorParams memory _params
    )
        DualOracleBase(
            DualOracleBaseParams({
                baseToken0: address(840),
                baseToken0Decimals: 18,
                quoteToken0: _params.fxsErc20,
                quoteToken0Decimals: 18,
                baseToken1: address(840),
                baseToken1Decimals: 18,
                quoteToken1: _params.fxsErc20,
                quoteToken1Decimals: 18
            })
        )
        Timelock2Step()
        ChainlinkOracleWithMaxDelay(
            ChainlinkOracleWithMaxDelayParams({
                chainlinkFeedAddress: _params.fxsRedstoneFeed,
                maximumOracleDelay: _params.maximumOracleDelay
            })
        )
        FraxSwapTwapOracle(
            FraxSwapOracleParams({
                fraxswapPair: _params.fraxswapPair,
                toQuote: _params.fxsErc20,
                twapDuration: _params.twapDuration
            })
        )
    {
        _setTimelock({ _newTimelock: _params.timelockAddress });
        _registerInterface({ interfaceId: type(IDualOracle).interfaceId });
        _registerInterface({ interfaceId: type(ITimelock2Step).interfaceId });

        FXS_ERC20 = _params.fxsErc20;
    }

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

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

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

    /// @notice The ```setMaximumOracleDelay``` function set the max oracle delay for the Fxs/USD Redstone oracle
    /// @dev Requires msg.sender to be the timelock address
    /// @param _newMaxOracleDelay The new max oracle delay
    function setMaximumOracleDelay(uint256 _newMaxOracleDelay) external override {
        _requireTimelock();
        _setMaximumOracleDelay({ _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 ```getFxsPerUsdRedStone``` function returns the amount of fxs per 1 USD
    /// @return _isBadData Whether the data returned from the oracle is stale
    /// @return _fxsPerUsd The amount of fxs per unit of USD
    function getFxsPerUsdRedStone() public view returns (bool _isBadData, uint256 _fxsPerUsd) {
        (bool isBadData, , uint256 usdPerFxs) = _getChainlinkPrice();
        _isBadData = isBadData;
        _fxsPerUsd = (CHAINLINK_FEED_PRECISION * ORACLE_PRECISION) / usdPerFxs;
    }

    /// @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 _fxsPerUsdRedStone) = getFxsPerUsdRedStone();

        uint256 _fraxPerFxsTwap = _getTwapFraxSwapPair();
        uint256 _fxsPerFraxTwap = (ORACLE_PRECISION ** 2) / _fraxPerFxsTwap;

        _isBadData = isBadData;
        _priceLow = _fxsPerFraxTwap < _fxsPerUsdRedStone ? _fxsPerFraxTwap : _fxsPerUsdRedStone;
        _priceHigh = _fxsPerUsdRedStone > _fxsPerFraxTwap ? _fxsPerUsdRedStone : _fxsPerFraxTwap;
    }

    /// @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;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// =================== 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();
    }
}

File 5 of 17 : 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: 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: 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 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: 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: 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":"fxsErc20","type":"address"},{"internalType":"address","name":"fxsRedstoneFeed","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":"SetMaximumOracleDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"uint256","name":"oldMaxOracleDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxOracleDelay","type":"uint256"}],"name":"SetMaximumOracleDelay","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":"CHAINLINK_FEED_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CHAINLINK_FEED_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"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":"FXS_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":"getChainlinkPrice","outputs":[{"internalType":"bool","name":"_isBadData","type":"bool"},{"internalType":"uint256","name":"_updatedAt","type":"uint256"},{"internalType":"uint256","name":"_price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFxsPerUsdRedStone","outputs":[{"internalType":"bool","name":"_isBadData","type":"bool"},{"internalType":"uint256","name":"_fxsPerUsd","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":"maximumOracleDelay","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":"setMaximumOracleDelay","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"}]

61026060405234801562000011575f80fd5b5060405162002347380380620023478339810160408190526200003491620006c8565b6040805180820182526060808401516001600160a01b0390811683526080808601516020808601919091528551808501875287518416815287870180518516828401528289015163ffffffff168289015287516101008082018a526103488083526012958301868152845189169b84018c905298830186815283880191825260a080850188815295518a1660c080870191825260e08088019a8b529e909a52915160ff9081169182905291518a1690985295518616909a528151871690529551831661012081905297519094166101405292511661016052929390926200011c919062000789565b610180526101605160e05162000133919062000789565b6101a05250600180546001600160a01b0319163317905580516001600160a01b03166101c08190526040808301516004805463ffffffff909216600160a01b0263ffffffff60a01b199092169190911781558151630dfe168160e01b815291515f9392630dfe168192818101926020929091908290030181865afa158015620001be573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001e49190620007b2565b90505f6101c0516001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000227573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200024d9190620007b2565b905082602001516001600160a01b0316826001600160a01b031603620002bb57600480546020850151600160c01b600164ff0000000160a01b03199092166001600160a01b039182161791909117909155600380546001600160a01b0319169183169190911790556200032c565b82602001516001600160a01b0316816001600160a01b03160362000313576020830151600480546001600160a01b03199081166001600160a01b0393841617909155600380549091169184169190911790556200032c565b604051630c40208b60e01b815260040160405180910390fd5b60056101c0516001600160a01b0316637fa2ee6e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200036e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620003949190620007d5565b1015620003b4576040516355c21b8960e11b815260040160405180910390fd5b816001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003f1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620004179190620007ed565b60ff166012146200043b57604051632754761960e01b815260040160405180910390fd5b806001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000478573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200049e9190620007ed565b60ff16601214620004c257604051632754761960e01b815260040160405180910390fd5b505050620004dd63034a813d60e01b620005ba60201b60201c565b80516001600160a01b03166101e08190526040805163313ce56760e01b8152905163313ce567916004808201926020929091908290030181865afa15801562000528573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200054e9190620007ed565b60ff166102008190526200056490600a6200090a565b610220526020015160055560a08101516200057f906200063d565b6200059163415f130360e01b620005ba565b620005a3632fa3fc3160e21b620005ba565b604001516001600160a01b03166102405262000917565b6001600160e01b03198082169003620006195760405162461bcd60e51b815260206004820152601c60248201527f4552433136353a20696e76616c696420696e7465726661636520696400000000604482015260640160405180910390fd5b6001600160e01b0319165f908152600260205260409020805460ff19166001179055565b6001546040516001600160a01b038084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b80516001600160a01b0381168114620006af575f80fd5b919050565b805163ffffffff81168114620006af575f80fd5b5f60c08284031215620006d9575f80fd5b60405160c081016001600160401b03811182821017156200070857634e487b7160e01b5f52604160045260245ffd5b604052620007168362000698565b81526200072660208401620006b4565b6020820152620007396040840162000698565b60408201526200074c6060840162000698565b6060820152608083015160808201526200076960a0840162000698565b60a08201529392505050565b634e487b7160e01b5f52601160045260245ffd5b8181035f831280158383131683831282161715620007ab57620007ab62000775565b5092915050565b5f60208284031215620007c3575f80fd5b620007ce8262000698565b9392505050565b5f60208284031215620007e6575f80fd5b5051919050565b5f60208284031215620007fe575f80fd5b815160ff81168114620007ce575f80fd5b600181815b808511156200084f57815f190482111562000833576200083362000775565b808516156200084157918102915b93841c939080029062000814565b509250929050565b5f82620008675750600162000904565b816200087557505f62000904565b81600181146200088e57600281146200089957620008b9565b600191505062000904565b60ff841115620008ad57620008ad62000775565b50506001821b62000904565b5060208310610133831016604e8410600b8410161715620008de575081810a62000904565b620008ea83836200080f565b805f190482111562000900576200090062000775565b0290505b92915050565b5f620007ce838362000857565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c0516101e05161020051610220516102405161193362000a145f395f6105c901525f81816105450152610f0401525f61051e01525f8181610380015261106e01525f818161057b0152818161076001528181610805015281816108a301528181610a990152610bd301525f818161023d01528181610e1a01528181610e430152610e8601525f81816105f001528181610d7901528181610da20152610de501525f6103f901525f61035901525f61068101525f61033201525f6104d701525f61049001525f61065a01525f61063301526119335ff3fe608060405234801561000f575f80fd5b5060043610610234575f3560e01c806359c909e11161013d578063bd9a548b116100b8578063d2333be711610088578063e5a66dfa1161006e578063e5a66dfa14610655578063f097486c1461067c578063f6ccaad4146106a3575f80fd5b8063d2333be71461061b578063e0d2e7801461062e575f80fd5b8063bd9a548b146105bc578063c4aaa748146105c4578063c82f2b12146105eb578063cede91a414610612575f80fd5b80638b8b2c911161010d5780639c0d313f116100f35780639c0d313f146105675780639f50f76114610576578063a05ccefa1461059d575f80fd5b80638b8b2c91146105195780638e7dc4c014610540575f80fd5b806359c909e11461048b5780635f9a63e4146104b2578063781097d0146104d257806388c210f7146104f9575f80fd5b806326d89545116101cd57806343aae02d1161019d5780634bc66f32116101835780634bc66f321461045b5780634d3375e81461047b5780634f8b4ae714610483575f80fd5b806343aae02d146104405780634501409514610448575f80fd5b806326d89545146103a2578063313ce567146103df57806337f85f66146103f45780633aeef3d31461041b575f80fd5b8063090f3f5011610208578063090f3f50146102e9578063116d79761461032d578063208880041461035457806320bf30fc1461037b575f80fd5b806232e91a1461023857806301ffc9a71461027257806306fdde0314610295578063075a194e146102d4575b5f80fd5b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6102856102803660046113af565b6106ab565b6040519015158152602001610269565b604080518082018252601f81527f4658532052656453746f6e65204475616c204f7261636c65202b2054574150006020820152905161026991906113ee565b6102e76102e2366004611468565b610732565b005b5f546103089073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610269565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b6004546103ca9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610269565b60125b60405160ff9091168152602001610269565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b610423610746565b604080519315158452602084019290925290820152606001610269565b61025f61075c565b6102e7610456366004611483565b610d4e565b6001546103089073ffffffffffffffffffffffffffffffffffffffff1681565b610423610d5f565b6102e7610ec0565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b6003546103089073ffffffffffffffffffffffffffffffffffffffff1681565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6004546103089073ffffffffffffffffffffffffffffffffffffffff1681565b6103e27f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f670de0b6b3a764000081565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b6105a5610ee4565b604080519215158352602083019190915201610269565b610423610f3f565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f60055481565b6102e76106293660046114b6565b610f4a565b6103087f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6102e7610f5b565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061072c57507fffffffff0000000000000000000000000000000000000000000000000000000082165f9081526002602052604090205460ff165b92915050565b61073a610f6b565b61074381610fbc565b50565b5f805f610751611067565b925092509250909192565b5f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16637fa2ee6e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107c7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107eb91906114cd565b90505f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166327e73836610835600185611511565b6040518263ffffffff1660e01b815260040161085391815260200190565b606060405180830381865afa15801561086e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108929190611524565b905042815f015110156109ff575f807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561090a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061092e91906115c5565b5090925090505f61094464010000000042611636565b8451909150810363ffffffff81166109838561095f86611124565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169061114e565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16028560200181815101915081815250508063ffffffff166109c58461095f87611124565b6040870180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216929092020190525063ffffffff16835250505b610a2060405180606001604052805f81526020015f81526020015f81525090565b6004545f908190610a519060289074010000000000000000000000000000000000000000900463ffffffff16611649565b63ffffffff1690505b60045474010000000000000000000000000000000000000000900463ffffffff16811015610bb25773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166327e73836610ac983600161166b565b610ad39088611511565b6040518263ffffffff1660e01b8152600401610af191815260200190565b606060405180830381865afa158015610b0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b309190611524565b600454815186519295507401000000000000000000000000000000000000000090910463ffffffff1691031015610b6957809150610b6e565b610bb2565b600454610b9b9060149074010000000000000000000000000000000000000000900463ffffffff16611649565b610bab9063ffffffff168261166b565b9050610a5a565b505b83811015610cac5773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166327e73836610c0383600161166b565b610c0d9087611511565b6040518263ffffffff1660e01b8152600401610c2b91815260200190565b606060405180830381865afa158015610c46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c6a9190611524565b600454815185519294507401000000000000000000000000000000000000000090910463ffffffff16910311610cac5780610ca48161167e565b915050610bb4565b6004547801000000000000000000000000000000000000000000000000900460ff1615610d0f575f825f0151845f01510363ffffffff16836020015185602001510381610cfb57610cfb611609565b049050610d0781611170565b955050610d47565b5f825f0151845f01510363ffffffff16836040015185604001510381610d3757610d37611609565b049050610d4381611170565b9550505b5050505090565b610d56610f6b565b61074381611182565b5f805f805f80610d6d6111f6565b9250925092508295505f7f000000000000000000000000000000000000000000000000000000000000000013610de057610dc67f00000000000000000000000000000000000000000000000000000000000000006116b5565b610dd190600a611809565b610ddb9083611814565b610e15565b610e0b7f0000000000000000000000000000000000000000000000000000000000000000600a611809565b610e159083611827565b94505f7f000000000000000000000000000000000000000000000000000000000000000013610e8157610e677f00000000000000000000000000000000000000000000000000000000000000006116b5565b610e7290600a611809565b610e7c9082611814565b610eb6565b610eac7f0000000000000000000000000000000000000000000000000000000000000000600a611809565b610eb69082611827565b9350505050909192565b610ec8610f6b565b610ed0611261565b610ed95f611182565b610ee25f6112b1565b565b5f805f80610ef0611067565b925050915081935080670de0b6b3a76400007f0000000000000000000000000000000000000000000000000000000000000000610f2d9190611827565b610f379190611814565b925050509091565b5f805f6107516111f6565b610f52610f6b565b6107438161133e565b610f63611261565b610ee261137f565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ee2576040517f1c0be90a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546040805163ffffffff740100000000000000000000000000000000000000009093048316815291831660208301527fe99a18add462219d56cbe6eacbd37b6795ea7beb885a903238a2fe939b6dfa24910160405180910390a16004805463ffffffff90921674010000000000000000000000000000000000000000027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b5f805f805f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156110d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f99190611857565b509350509250505f8213158061111957506005546111178242611511565b115b959094509092509050565b5f61072c6e0100000000000000000000000000006dffffffffffffffffffffffffffff84166118a3565b5f6111696dffffffffffffffffffffffffffff8316846118ea565b9392505050565b5f61072c6612725dd1d243ab83611814565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a9190a350565b5f805f805f611203610ee4565b915091505f61121061075c565b90505f816112276002670de0b6b3a7640000611918565b6112319190611814565b90508396508281106112435782611245565b805b95508083116112545780611256565b825b945050505050909192565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610ee2576040517ff5c49e6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60055460408051918252602082018390527fd72ef688fa430b6a285b84371ba35e8a8e0762b32c1deb7be9d9c111ca79f5ea910160405180910390a1600555565b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610ee2336112b1565b5f602082840312156113bf575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611169575f80fd5b5f6020808352835180828501525f5b81811015611419578581018301518582016040015282016113fd565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b63ffffffff81168114610743575f80fd5b5f60208284031215611478575f80fd5b813561116981611457565b5f60208284031215611493575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114611169575f80fd5b5f602082840312156114c6575f80fd5b5035919050565b5f602082840312156114dd575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561072c5761072c6114e4565b5f60608284031215611534575f80fd5b6040516060810181811067ffffffffffffffff8211171561157c577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b80604052508251815260208301516020820152604083015160408201528091505092915050565b80516dffffffffffffffffffffffffffff811681146115c0575f80fd5b919050565b5f805f606084860312156115d7575f80fd5b6115e0846115a3565b92506115ee602085016115a3565b915060408401516115fe81611457565b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261164457611644611609565b500690565b5f63ffffffff8084168061165f5761165f611609565b92169190910492915050565b8082018082111561072c5761072c6114e4565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036116ae576116ae6114e4565b5060010190565b5f7f800000000000000000000000000000000000000000000000000000000000000082036116e5576116e56114e4565b505f0390565b600181815b8085111561174457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561172a5761172a6114e4565b8085161561173757918102915b93841c93908002906116f0565b509250929050565b5f8261175a5750600161072c565b8161176657505f61072c565b816001811461177c5760028114611786576117a2565b600191505061072c565b60ff841115611797576117976114e4565b50506001821b61072c565b5060208310610133831016604e8410600b84101617156117c5575081810a61072c565b6117cf83836116eb565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611801576118016114e4565b029392505050565b5f611169838361174c565b5f8261182257611822611609565b500490565b808202811582820484141761072c5761072c6114e4565b805169ffffffffffffffffffff811681146115c0575f80fd5b5f805f805f60a0868803121561186b575f80fd5b6118748661183e565b94506020860151935060408601519250606086015191506118976080870161183e565b90509295509295909350565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8281168282168181028316929181158285048214176118e1576118e16114e4565b50505092915050565b5f7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8084168061165f5761165f611609565b5f61116960ff84168361174c56fea164736f6c6343000814000a000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f0000000000000000000000000000000000000000000000000000000000000f3c000000000000000000000000fc00000000000000000000000000000000000002000000000000000000000000bf228a9131ab3bb8ca8c7a4ad574932253d99cd10000000000000000000000000000000000000000000000000000000000000f3c000000000000000000000000c16068d1ca7e24e20e56bb70af4d00d92aa4f0b2

Deployed Bytecode

0x608060405234801561000f575f80fd5b5060043610610234575f3560e01c806359c909e11161013d578063bd9a548b116100b8578063d2333be711610088578063e5a66dfa1161006e578063e5a66dfa14610655578063f097486c1461067c578063f6ccaad4146106a3575f80fd5b8063d2333be71461061b578063e0d2e7801461062e575f80fd5b8063bd9a548b146105bc578063c4aaa748146105c4578063c82f2b12146105eb578063cede91a414610612575f80fd5b80638b8b2c911161010d5780639c0d313f116100f35780639c0d313f146105675780639f50f76114610576578063a05ccefa1461059d575f80fd5b80638b8b2c91146105195780638e7dc4c014610540575f80fd5b806359c909e11461048b5780635f9a63e4146104b2578063781097d0146104d257806388c210f7146104f9575f80fd5b806326d89545116101cd57806343aae02d1161019d5780634bc66f32116101835780634bc66f321461045b5780634d3375e81461047b5780634f8b4ae714610483575f80fd5b806343aae02d146104405780634501409514610448575f80fd5b806326d89545146103a2578063313ce567146103df57806337f85f66146103f45780633aeef3d31461041b575f80fd5b8063090f3f5011610208578063090f3f50146102e9578063116d79761461032d578063208880041461035457806320bf30fc1461037b575f80fd5b806232e91a1461023857806301ffc9a71461027257806306fdde0314610295578063075a194e146102d4575b5f80fd5b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b6102856102803660046113af565b6106ab565b6040519015158152602001610269565b604080518082018252601f81527f4658532052656453746f6e65204475616c204f7261636c65202b2054574150006020820152905161026991906113ee565b6102e76102e2366004611468565b610732565b005b5f546103089073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610269565b6103087f000000000000000000000000000000000000000000000000000000000000034881565b6103087f000000000000000000000000000000000000000000000000000000000000034881565b6103087f000000000000000000000000bf228a9131ab3bb8ca8c7a4ad574932253d99cd181565b6004546103ca9074010000000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610269565b60125b60405160ff9091168152602001610269565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b610423610746565b604080519315158452602084019290925290820152606001610269565b61025f61075c565b6102e7610456366004611483565b610d4e565b6001546103089073ffffffffffffffffffffffffffffffffffffffff1681565b610423610d5f565b6102e7610ec0565b6103087f000000000000000000000000fc0000000000000000000000000000000000000281565b6003546103089073ffffffffffffffffffffffffffffffffffffffff1681565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b6004546103089073ffffffffffffffffffffffffffffffffffffffff1681565b6103e27f000000000000000000000000000000000000000000000000000000000000000881565b61025f7f0000000000000000000000000000000000000000000000000000000005f5e10081565b61025f670de0b6b3a764000081565b6103087f000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f81565b6105a5610ee4565b604080519215158352602083019190915201610269565b610423610f3f565b6103087f000000000000000000000000fc0000000000000000000000000000000000000281565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b61025f60055481565b6102e76106293660046114b6565b610f4a565b6103087f000000000000000000000000fc0000000000000000000000000000000000000281565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b6102e7610f5b565b5f7f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316148061072c57507fffffffff0000000000000000000000000000000000000000000000000000000082165f9081526002602052604090205460ff165b92915050565b61073a610f6b565b61074381610fbc565b50565b5f805f610751611067565b925092509250909192565b5f807f000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f73ffffffffffffffffffffffffffffffffffffffff16637fa2ee6e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107c7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107eb91906114cd565b90505f73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f166327e73836610835600185611511565b6040518263ffffffff1660e01b815260040161085391815260200190565b606060405180830381865afa15801561086e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108929190611524565b905042815f015110156109ff575f807f000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f73ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561090a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061092e91906115c5565b5090925090505f61094464010000000042611636565b8451909150810363ffffffff81166109838561095f86611124565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169061114e565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16028560200181815101915081815250508063ffffffff166109c58461095f87611124565b6040870180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216929092020190525063ffffffff16835250505b610a2060405180606001604052805f81526020015f81526020015f81525090565b6004545f908190610a519060289074010000000000000000000000000000000000000000900463ffffffff16611649565b63ffffffff1690505b60045474010000000000000000000000000000000000000000900463ffffffff16811015610bb25773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f166327e73836610ac983600161166b565b610ad39088611511565b6040518263ffffffff1660e01b8152600401610af191815260200190565b606060405180830381865afa158015610b0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b309190611524565b600454815186519295507401000000000000000000000000000000000000000090910463ffffffff1691031015610b6957809150610b6e565b610bb2565b600454610b9b9060149074010000000000000000000000000000000000000000900463ffffffff16611649565b610bab9063ffffffff168261166b565b9050610a5a565b505b83811015610cac5773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f166327e73836610c0383600161166b565b610c0d9087611511565b6040518263ffffffff1660e01b8152600401610c2b91815260200190565b606060405180830381865afa158015610c46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c6a9190611524565b600454815185519294507401000000000000000000000000000000000000000090910463ffffffff16910311610cac5780610ca48161167e565b915050610bb4565b6004547801000000000000000000000000000000000000000000000000900460ff1615610d0f575f825f0151845f01510363ffffffff16836020015185602001510381610cfb57610cfb611609565b049050610d0781611170565b955050610d47565b5f825f0151845f01510363ffffffff16836040015185604001510381610d3757610d37611609565b049050610d4381611170565b9550505b5050505090565b610d56610f6b565b61074381611182565b5f805f805f80610d6d6111f6565b9250925092508295505f7f000000000000000000000000000000000000000000000000000000000000000013610de057610dc67f00000000000000000000000000000000000000000000000000000000000000006116b5565b610dd190600a611809565b610ddb9083611814565b610e15565b610e0b7f0000000000000000000000000000000000000000000000000000000000000000600a611809565b610e159083611827565b94505f7f000000000000000000000000000000000000000000000000000000000000000013610e8157610e677f00000000000000000000000000000000000000000000000000000000000000006116b5565b610e7290600a611809565b610e7c9082611814565b610eb6565b610eac7f0000000000000000000000000000000000000000000000000000000000000000600a611809565b610eb69082611827565b9350505050909192565b610ec8610f6b565b610ed0611261565b610ed95f611182565b610ee25f6112b1565b565b5f805f80610ef0611067565b925050915081935080670de0b6b3a76400007f0000000000000000000000000000000000000000000000000000000005f5e100610f2d9190611827565b610f379190611814565b925050509091565b5f805f6107516111f6565b610f52610f6b565b6107438161133e565b610f63611261565b610ee261137f565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ee2576040517f1c0be90a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6004546040805163ffffffff740100000000000000000000000000000000000000009093048316815291831660208301527fe99a18add462219d56cbe6eacbd37b6795ea7beb885a903238a2fe939b6dfa24910160405180910390a16004805463ffffffff90921674010000000000000000000000000000000000000000027fffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b5f805f805f7f000000000000000000000000bf228a9131ab3bb8ca8c7a4ad574932253d99cd173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156110d5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f99190611857565b509350509250505f8213158061111957506005546111178242611511565b115b959094509092509050565b5f61072c6e0100000000000000000000000000006dffffffffffffffffffffffffffff84166118a3565b5f6111696dffffffffffffffffffffffffffff8316846118ea565b9392505050565b5f61072c6612725dd1d243ab83611814565b5f80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217835560015460405192939116917f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a9190a350565b5f805f805f611203610ee4565b915091505f61121061075c565b90505f816112276002670de0b6b3a7640000611918565b6112319190611814565b90508396508281106112435782611245565b805b95508083116112545780611256565b825b945050505050909192565b5f5473ffffffffffffffffffffffffffffffffffffffff163314610ee2576040517ff5c49e6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60015460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc6905f90a3600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60055460408051918252602082018390527fd72ef688fa430b6a285b84371ba35e8a8e0762b32c1deb7be9d9c111ca79f5ea910160405180910390a1600555565b5f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610ee2336112b1565b5f602082840312156113bf575f80fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114611169575f80fd5b5f6020808352835180828501525f5b81811015611419578581018301518582016040015282016113fd565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b63ffffffff81168114610743575f80fd5b5f60208284031215611478575f80fd5b813561116981611457565b5f60208284031215611493575f80fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114611169575f80fd5b5f602082840312156114c6575f80fd5b5035919050565b5f602082840312156114dd575f80fd5b5051919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561072c5761072c6114e4565b5f60608284031215611534575f80fd5b6040516060810181811067ffffffffffffffff8211171561157c577f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b80604052508251815260208301516020820152604083015160408201528091505092915050565b80516dffffffffffffffffffffffffffff811681146115c0575f80fd5b919050565b5f805f606084860312156115d7575f80fd5b6115e0846115a3565b92506115ee602085016115a3565b915060408401516115fe81611457565b809150509250925092565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f8261164457611644611609565b500690565b5f63ffffffff8084168061165f5761165f611609565b92169190910492915050565b8082018082111561072c5761072c6114e4565b5f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036116ae576116ae6114e4565b5060010190565b5f7f800000000000000000000000000000000000000000000000000000000000000082036116e5576116e56114e4565b505f0390565b600181815b8085111561174457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561172a5761172a6114e4565b8085161561173757918102915b93841c93908002906116f0565b509250929050565b5f8261175a5750600161072c565b8161176657505f61072c565b816001811461177c5760028114611786576117a2565b600191505061072c565b60ff841115611797576117976114e4565b50506001821b61072c565b5060208310610133831016604e8410600b84101617156117c5575081810a61072c565b6117cf83836116eb565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115611801576118016114e4565b029392505050565b5f611169838361174c565b5f8261182257611822611609565b500490565b808202811582820484141761072c5761072c6114e4565b805169ffffffffffffffffffff811681146115c0575f80fd5b5f805f805f60a0868803121561186b575f80fd5b6118748661183e565b94506020860151935060408601519250606086015191506118976080870161183e565b90509295509295909350565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8281168282168181028316929181158285048214176118e1576118e16114e4565b50505092915050565b5f7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8084168061165f5761165f611609565b5f61116960ff84168361174c56fea164736f6c6343000814000a

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

000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f0000000000000000000000000000000000000000000000000000000000000f3c000000000000000000000000fc00000000000000000000000000000000000002000000000000000000000000bf228a9131ab3bb8ca8c7a4ad574932253d99cd10000000000000000000000000000000000000000000000000000000000000f3c000000000000000000000000c16068d1ca7e24e20e56bb70af4d00d92aa4f0b2

-----Decoded View---------------
Arg [0] : _params (tuple):
Arg [1] : fraxswapPair (address): 0xb4dA8dA10ffF1F6127ab71395053Aa1d499b503F
Arg [2] : twapDuration (uint32): 3900
Arg [3] : fxsErc20 (address): 0xFc00000000000000000000000000000000000002
Arg [4] : fxsRedstoneFeed (address): 0xbf228a9131AB3BB8ca8C7a4Ad574932253D99Cd1
Arg [5] : maximumOracleDelay (uint256): 3900
Arg [6] : timelockAddress (address): 0xc16068d1ca7E24E20e56bB70af4D00D92AA4f0b2


-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000b4da8da10fff1f6127ab71395053aa1d499b503f
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000f3c
Arg [2] : 000000000000000000000000fc00000000000000000000000000000000000002
Arg [3] : 000000000000000000000000bf228a9131ab3bb8ca8c7a4ad574932253d99cd1
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.