编译器
0.8.19+commit.7dd6d404
文件 1 的 24:AggregatorV3Interface.sol
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
);
}
文件 2 的 24:CurvePoolEmaPriceOracleWithMinMax.sol
pragma solidity ^0.8.19;
import { ERC165Storage } from "@openzeppelin/contracts/utils/introspection/ERC165Storage.sol";
import {
ICurvePoolEmaPriceOracleWithMinMax
} from "interfaces/oracles/abstracts/ICurvePoolEmaPriceOracleWithMinMax.sol";
import { IEmaPriceOracleStableSwap } from "interfaces/IEmaPriceOracleStableSwap.sol";
struct ConstructorParams {
address curvePoolEmaPriceOracleAddress;
uint256 minimumCurvePoolEma;
uint256 maximumCurvePoolEma;
}
abstract contract CurvePoolEmaPriceOracleWithMinMax is ERC165Storage, ICurvePoolEmaPriceOracleWithMinMax {
address public immutable CURVE_POOL_EMA_PRICE_ORACLE;
uint256 public constant CURVE_POOL_EMA_PRICE_ORACLE_PRECISION = 1e18;
uint256 public minimumCurvePoolEma;
uint256 public maximumCurvePoolEma;
constructor(ConstructorParams memory _params) {
_registerInterface({ interfaceId: type(ICurvePoolEmaPriceOracleWithMinMax).interfaceId });
CURVE_POOL_EMA_PRICE_ORACLE = _params.curvePoolEmaPriceOracleAddress;
minimumCurvePoolEma = _params.minimumCurvePoolEma;
maximumCurvePoolEma = _params.maximumCurvePoolEma;
}
function _setMaximumCurvePoolEma(uint256 _maximumPrice) internal {
emit SetMaximumCurvePoolEma({ oldMaximum: maximumCurvePoolEma, newMaximum: _maximumPrice });
maximumCurvePoolEma = _maximumPrice;
}
function setMaximumCurvePoolEma(uint256 _maximumPrice) external virtual;
function _setMinimumCurvePoolEma(uint256 _minimumPrice) internal {
emit SetMinimumCurvePoolEma({ oldMinimum: minimumCurvePoolEma, newMinimum: _minimumPrice });
minimumCurvePoolEma = _minimumPrice;
}
function setMinimumCurvePoolEma(uint256 _minimumPrice) external virtual;
function _getCurvePoolToken1EmaPrice() internal view returns (uint256 _token1Price) {
uint256 _priceRaw = IEmaPriceOracleStableSwap(CURVE_POOL_EMA_PRICE_ORACLE).price_oracle();
uint256 _price = _priceRaw > maximumCurvePoolEma ? maximumCurvePoolEma : _priceRaw;
_token1Price = _price < minimumCurvePoolEma ? minimumCurvePoolEma : _price;
}
function getCurvePoolToken1EmaPrice() external view returns (uint256 _emaPrice) {
return _getCurvePoolToken1EmaPrice();
}
}
文件 3 的 24:DualOracleBase.sol
pragma solidity ^0.8.19;
import "interfaces/IDualOracle.sol";
struct ConstructorParams {
address baseToken0;
uint8 baseToken0Decimals;
address quoteToken0;
uint8 quoteToken0Decimals;
address baseToken1;
uint8 baseToken1Decimals;
address quoteToken1;
uint8 quoteToken1Decimals;
}
abstract contract DualOracleBase is IDualOracle {
uint256 public constant ORACLE_PRECISION = 1e18;
address public immutable QUOTE_TOKEN_0;
uint256 public immutable QUOTE_TOKEN_0_DECIMALS;
address public immutable QUOTE_TOKEN_1;
uint256 public immutable QUOTE_TOKEN_1_DECIMALS;
address public immutable BASE_TOKEN_0;
uint256 public immutable BASE_TOKEN_0_DECIMALS;
address public immutable BASE_TOKEN_1;
uint256 public immutable BASE_TOKEN_1_DECIMALS;
int256 public immutable NORMALIZATION_0;
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);
}
function decimals() external pure returns (uint8) {
return 18;
}
}
文件 4 的 24:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 5 的 24:ERC165Storage.sol
pragma solidity ^0.8.0;
import "./ERC165.sol";
abstract contract ERC165Storage is ERC165 {
mapping(bytes4 => bool) private _supportedInterfaces;
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return super.supportsInterface(interfaceId) || _supportedInterfaces[interfaceId];
}
function _registerInterface(bytes4 interfaceId) internal virtual {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
文件 6 的 24:EthUsdChainlinkOracleWithMaxDelay.sol
pragma solidity ^0.8.19;
import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import { ERC165Storage } from "@openzeppelin/contracts/utils/introspection/ERC165Storage.sol";
import {
IEthUsdChainlinkOracleWithMaxDelay
} from "interfaces/oracles/abstracts/IEthUsdChainlinkOracleWithMaxDelay.sol";
struct ConstructorParams {
address ethUsdChainlinkFeedAddress;
uint256 maxEthUsdOracleDelay;
}
abstract contract EthUsdChainlinkOracleWithMaxDelay is ERC165Storage, IEthUsdChainlinkOracleWithMaxDelay {
address public immutable ETH_USD_CHAINLINK_FEED_ADDRESS;
uint8 public immutable ETH_USD_CHAINLINK_FEED_DECIMALS;
uint256 public immutable ETH_USD_CHAINLINK_FEED_PRECISION;
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;
}
function _setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) internal {
emit SetMaximumEthUsdOracleDelay({
oldMaxOracleDelay: maximumEthUsdOracleDelay,
newMaxOracleDelay: _newMaxOracleDelay
});
maximumEthUsdOracleDelay = _newMaxOracleDelay;
}
function setMaximumEthUsdOracleDelay(uint256 _newMaxOracleDelay) external virtual;
function _getEthUsdChainlinkPrice()
internal
view
returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth)
{
(, int256 _answer, , uint256 _ethUsdChainlinkUpdatedAt, ) = AggregatorV3Interface(
ETH_USD_CHAINLINK_FEED_ADDRESS
).latestRoundData();
_isBadData = _answer <= 0 || ((block.timestamp - _ethUsdChainlinkUpdatedAt) > maximumEthUsdOracleDelay);
_updatedAt = _ethUsdChainlinkUpdatedAt;
_usdPerEth = uint256(_answer);
}
function getEthUsdChainlinkPrice()
external
view
virtual
returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerEth)
{
(_isBadData, _updatedAt, _usdPerEth) = _getEthUsdChainlinkPrice();
}
}
文件 7 的 24:FraxUsdChainlinkOracleWithMaxDelay.sol
pragma solidity ^0.8.19;
import { AggregatorV3Interface } from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import { ERC165Storage } from "@openzeppelin/contracts/utils/introspection/ERC165Storage.sol";
import {
IFraxUsdChainlinkOracleWithMaxDelay
} from "interfaces/oracles/abstracts/IFraxUsdChainlinkOracleWithMaxDelay.sol";
struct ConstructorParams {
address fraxUsdChainlinkFeedAddress;
uint256 fraxUsdMaximumOracleDelay;
}
abstract contract FraxUsdChainlinkOracleWithMaxDelay is ERC165Storage, IFraxUsdChainlinkOracleWithMaxDelay {
address public immutable FRAX_USD_CHAINLINK_FEED_ADDRESS;
uint8 public immutable FRAX_USD_CHAINLINK_FEED_DECIMALS;
uint256 public immutable FRAX_USD_CHAINLINK_FEED_PRECISION;
uint256 public maximumFraxUsdOracleDelay;
constructor(ConstructorParams memory _params) {
_registerInterface({ interfaceId: type(IFraxUsdChainlinkOracleWithMaxDelay).interfaceId });
FRAX_USD_CHAINLINK_FEED_ADDRESS = _params.fraxUsdChainlinkFeedAddress;
FRAX_USD_CHAINLINK_FEED_DECIMALS = AggregatorV3Interface(FRAX_USD_CHAINLINK_FEED_ADDRESS).decimals();
FRAX_USD_CHAINLINK_FEED_PRECISION = 10 ** uint256(FRAX_USD_CHAINLINK_FEED_DECIMALS);
maximumFraxUsdOracleDelay = _params.fraxUsdMaximumOracleDelay;
}
function _setMaximumFraxUsdOracleDelay(uint256 _newMaxOracleDelay) internal {
emit SetMaximumFraxUsdOracleDelay({
oldMaxOracleDelay: maximumFraxUsdOracleDelay,
newMaxOracleDelay: _newMaxOracleDelay
});
maximumFraxUsdOracleDelay = _newMaxOracleDelay;
}
function setMaximumFraxUsdOracleDelay(uint256 _newMaxOracleDelay) external virtual;
function _getFraxUsdChainlinkPrice()
internal
view
returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerFrax)
{
(, int256 _answer, , uint256 _fraxUsdChainlinkUpdatedAt, ) = AggregatorV3Interface(
FRAX_USD_CHAINLINK_FEED_ADDRESS
).latestRoundData();
_isBadData = _answer <= 0 || ((block.timestamp - _fraxUsdChainlinkUpdatedAt) > maximumFraxUsdOracleDelay);
_updatedAt = _fraxUsdChainlinkUpdatedAt;
_usdPerFrax = uint256(_answer);
}
function getFraxUsdChainlinkPrice()
external
view
virtual
returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerFrax)
{
(_isBadData, _updatedAt, _usdPerFrax) = _getFraxUsdChainlinkPrice();
}
}
文件 8 的 24:FrxEthEthDualOracle.sol
pragma solidity ^0.8.19;
import { ERC165Storage } from "@openzeppelin/contracts/utils/introspection/ERC165Storage.sol";
import { Timelock2Step } from "frax-std/access-control/v1/Timelock2Step.sol";
import { ITimelock2Step } from "frax-std/access-control/v1/interfaces/ITimelock2Step.sol";
import { DualOracleBase, ConstructorParams as DualOracleBaseParams } from "src/DualOracleBase.sol";
import {
UniswapV3SingleTwapOracle,
ConstructorParams as UniswapV3SingleTwapOracleParams
} from "./abstracts/UniswapV3SingleTwapOracle.sol";
import {
EthUsdChainlinkOracleWithMaxDelay,
ConstructorParams as EthUsdChainlinkOracleWithMaxDelayParams
} from "./abstracts/EthUsdChainlinkOracleWithMaxDelay.sol";
import {
CurvePoolEmaPriceOracleWithMinMax,
ConstructorParams as CurvePoolEmaPriceOracleWithMinMaxParams
} from "./abstracts/CurvePoolEmaPriceOracleWithMinMax.sol";
import {
FraxUsdChainlinkOracleWithMaxDelay,
ConstructorParams as FraxUsdChainlinkOracleWithMaxDelayParams
} from "./abstracts/FraxUsdChainlinkOracleWithMaxDelay.sol";
import { IDualOracle } from "interfaces/IDualOracle.sol";
import { IPriceSource } from "./interfaces/IPriceSource.sol";
import { IPriceSourceReceiver } from "./interfaces/IPriceSourceReceiver.sol";
struct ConstructorParams {
address baseToken0;
uint8 baseToken0Decimals;
address quoteToken0;
uint8 quoteToken0Decimals;
address baseToken1;
uint8 baseToken1Decimals;
address quoteToken1;
uint8 quoteToken1Decimals;
address frxEthErc20;
address fraxErc20;
address uniV3PairAddress;
uint32 twapDuration;
address fraxUsdChainlinkFeedAddress;
uint256 fraxUsdMaximumOracleDelay;
address ethUsdChainlinkFeed;
uint256 maxEthUsdOracleDelay;
address curvePoolEmaPriceOracleAddress;
uint256 minimumCurvePoolEma;
uint256 maximumCurvePoolEma;
address timelockAddress;
}
contract FrxEthEthDualOracle is
DualOracleBase,
CurvePoolEmaPriceOracleWithMinMax,
UniswapV3SingleTwapOracle,
FraxUsdChainlinkOracleWithMaxDelay,
EthUsdChainlinkOracleWithMaxDelay,
IPriceSource,
Timelock2Step
{
address public immutable FRXETH_ERC20;
constructor(
ConstructorParams memory params
)
DualOracleBase(
DualOracleBaseParams({
baseToken0: params.baseToken0,
baseToken0Decimals: params.baseToken0Decimals,
quoteToken0: params.quoteToken0,
quoteToken0Decimals: params.quoteToken0Decimals,
baseToken1: params.baseToken1,
baseToken1Decimals: params.baseToken1Decimals,
quoteToken1: params.quoteToken1,
quoteToken1Decimals: params.quoteToken1Decimals
})
)
CurvePoolEmaPriceOracleWithMinMax(
CurvePoolEmaPriceOracleWithMinMaxParams({
curvePoolEmaPriceOracleAddress: params.curvePoolEmaPriceOracleAddress,
minimumCurvePoolEma: params.minimumCurvePoolEma,
maximumCurvePoolEma: params.maximumCurvePoolEma
})
)
UniswapV3SingleTwapOracle(
UniswapV3SingleTwapOracleParams({
uniswapV3PairAddress: params.uniV3PairAddress,
twapDuration: params.twapDuration,
baseToken: params.frxEthErc20,
quoteToken: params.fraxErc20
})
)
EthUsdChainlinkOracleWithMaxDelay(
EthUsdChainlinkOracleWithMaxDelayParams({
ethUsdChainlinkFeedAddress: params.ethUsdChainlinkFeed,
maxEthUsdOracleDelay: params.maxEthUsdOracleDelay
})
)
FraxUsdChainlinkOracleWithMaxDelay(
FraxUsdChainlinkOracleWithMaxDelayParams({
fraxUsdChainlinkFeedAddress: params.fraxUsdChainlinkFeedAddress,
fraxUsdMaximumOracleDelay: params.fraxUsdMaximumOracleDelay
})
)
Timelock2Step()
{
_setTimelock({ _newTimelock: params.timelockAddress });
_registerInterface({ interfaceId: type(IDualOracle).interfaceId });
_registerInterface({ interfaceId: type(ITimelock2Step).interfaceId });
_registerInterface({ interfaceId: type(IPriceSource).interfaceId });
FRXETH_ERC20 = params.frxEthErc20;
}
function name() external view virtual returns (string memory _name) {
_name = "frxEth Dual Oracle In Eth with Curve Pool EMA and Uniswap v3 TWAP and Frax and ETH Chainlink";
}
function setMinimumCurvePoolEma(uint256 minimumPrice) external override {
_requireTimelock();
_setMinimumCurvePoolEma({ _minimumPrice: minimumPrice });
}
function setMaximumCurvePoolEma(uint256 maximumPrice) external override {
_requireTimelock();
_setMaximumCurvePoolEma({ _maximumPrice: maximumPrice });
}
function setTwapDuration(uint32 newTwapDuration) external override {
_requireTimelock();
_setTwapDuration({ _newTwapDuration: newTwapDuration });
}
function setMaximumEthUsdOracleDelay(uint256 newMaxOracleDelay) external override {
_requireTimelock();
_setMaximumEthUsdOracleDelay({ _newMaxOracleDelay: newMaxOracleDelay });
}
function setMaximumFraxUsdOracleDelay(uint256 newMaxOracleDelay) external override {
_requireTimelock();
_setMaximumFraxUsdOracleDelay({ _newMaxOracleDelay: newMaxOracleDelay });
}
function addRoundData(IPriceSourceReceiver fraxOracle) external {
(bool isBadData, uint256 priceLow, uint256 priceHigh) = _getPrices();
fraxOracle.addRoundData({
isBadData: isBadData,
priceLow: uint104(priceLow),
priceHigh: uint104(priceHigh),
timestamp: uint40(block.timestamp)
});
}
function getCurveEmaEthPerFrxEth() public view returns (uint256 ethPerFrxEth) {
ethPerFrxEth = _getCurvePoolToken1EmaPrice();
}
function getChainlinkUsdPerFrax() public view returns (bool isBadData, uint256 usdPerFrax) {
(bool isBadDataChainlink, , uint256 usdPerFraxRaw) = _getFraxUsdChainlinkPrice();
isBadData = isBadDataChainlink;
usdPerFrax = (ORACLE_PRECISION * usdPerFraxRaw) / FRAX_USD_CHAINLINK_FEED_PRECISION;
}
function getUsdPerEthChainlink() public view returns (bool isBadData, uint256 usdPerEth) {
uint256 usdPerEthChainlinkRaw;
(isBadData, , usdPerEthChainlinkRaw) = _getEthUsdChainlinkPrice();
usdPerEth = (ORACLE_PRECISION * usdPerEthChainlinkRaw) / ETH_USD_CHAINLINK_FEED_PRECISION;
}
function _calculatePrices(
uint256 ethPerFrxEthCurveEma,
uint256 fraxPerFrxEthTwap,
bool isBadDataEthUsdChainlink,
uint256 usdPerEthChainlink,
bool isBadDataFraxUsdChainlink,
uint256 usdPerFraxChainlink
) internal view virtual returns (bool isBadData, uint256 priceLow, uint256 priceHigh) {
uint256 ethPerFrxEthRawTwap = (fraxPerFrxEthTwap * usdPerFraxChainlink) / usdPerEthChainlink;
uint256 _maximumCurvePoolEma = maximumCurvePoolEma;
uint256 _minimumCurvePoolEma = minimumCurvePoolEma;
uint256 twapEthPerFrxEthHighBounded = ethPerFrxEthRawTwap > _maximumCurvePoolEma
? _maximumCurvePoolEma
: ethPerFrxEthRawTwap;
uint256 twapEthPerFrxEth = twapEthPerFrxEthHighBounded < _minimumCurvePoolEma
? _minimumCurvePoolEma
: twapEthPerFrxEthHighBounded;
isBadData = isBadDataEthUsdChainlink || isBadDataFraxUsdChainlink;
priceLow = ethPerFrxEthCurveEma < twapEthPerFrxEth ? ethPerFrxEthCurveEma : twapEthPerFrxEth;
priceHigh = twapEthPerFrxEth > ethPerFrxEthCurveEma ? twapEthPerFrxEth : ethPerFrxEthCurveEma;
}
function calculatePrices(
uint256 ethPerFrxEthCurveEma,
uint256 fraxPerFrxEthTwap,
bool isBadDataEthUsdChainlink,
uint256 usdPerEthChainlink,
bool isBadDataFraxUsdChainlink,
uint256 usdPerFraxChainlink
) external view returns (bool isBadData, uint256 priceLow, uint256 priceHigh) {
(isBadData, priceLow, priceHigh) = _calculatePrices({
ethPerFrxEthCurveEma: ethPerFrxEthCurveEma,
fraxPerFrxEthTwap: fraxPerFrxEthTwap,
isBadDataEthUsdChainlink: isBadDataEthUsdChainlink,
usdPerEthChainlink: usdPerEthChainlink,
isBadDataFraxUsdChainlink: isBadDataFraxUsdChainlink,
usdPerFraxChainlink: usdPerFraxChainlink
});
}
function _getPrices() internal view returns (bool isBadData, uint256 priceLow, uint256 priceHigh) {
uint256 ethPerFrxEthCurveEma = getCurveEmaEthPerFrxEth();
uint256 fraxPerFrxEthTwap = _getUniswapV3Twap();
(bool isBadDataEthUsdChainlink, uint256 usdPerEthChainlink) = getUsdPerEthChainlink();
(bool isBadDataFraxUsdChainlink, uint256 usdPerFraxChainlink) = getChainlinkUsdPerFrax();
(isBadData, priceLow, priceHigh) = _calculatePrices({
ethPerFrxEthCurveEma: ethPerFrxEthCurveEma,
fraxPerFrxEthTwap: fraxPerFrxEthTwap,
isBadDataEthUsdChainlink: isBadDataEthUsdChainlink,
usdPerEthChainlink: usdPerEthChainlink,
isBadDataFraxUsdChainlink: isBadDataFraxUsdChainlink,
usdPerFraxChainlink: usdPerFraxChainlink
});
}
function getPrices() external view returns (bool isBadData, uint256 priceLow, uint256 priceHigh) {
(isBadData, priceLow, priceHigh) = _getPrices();
}
function getPricesNormalized()
external
view
override
returns (bool isBadDataNormal, uint256 priceLowNormal, uint256 priceHighNormal)
{
(isBadDataNormal, priceLowNormal, priceHighNormal) = _getPrices();
}
}
文件 9 的 24:ICurvePoolEmaPriceOracleWithMinMax.sol
pragma solidity 0.8.19;
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
interface ICurvePoolEmaPriceOracleWithMinMax is IERC165 {
event SetMaximumCurvePoolEma(uint256 oldMaximum, uint256 newMaximum);
event SetMinimumCurvePoolEma(uint256 oldMinimum, uint256 newMinimum);
function CURVE_POOL_EMA_PRICE_ORACLE() external view returns (address);
function CURVE_POOL_EMA_PRICE_ORACLE_PRECISION() external view returns (uint256);
function getCurvePoolToken1EmaPrice() external view returns (uint256 _emaPrice);
function maximumCurvePoolEma() external view returns (uint256);
function minimumCurvePoolEma() external view returns (uint256);
function setMaximumCurvePoolEma(uint256 _maximumPrice) external;
function setMinimumCurvePoolEma(uint256 _minimumPrice) external;
}
文件 10 的 24:IDualOracle.sol
pragma solidity 0.8.19;
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);
}
文件 11 的 24:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 12 的 24:IEmaPriceOracleStableSwap.sol
pragma solidity >=0.8.19;
interface IEmaPriceOracleStableSwap {
function price_oracle() external view returns (uint256);
}
文件 13 的 24:IEthUsdChainlinkOracleWithMaxDelay.sol
pragma solidity 0.8.19;
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;
}
文件 14 的 24:IFraxUsdChainlinkOracleWithMaxDelay.sol
pragma solidity 0.8.19;
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
interface IFraxUsdChainlinkOracleWithMaxDelay is IERC165 {
event SetMaximumFraxUsdOracleDelay(uint256 oldMaxOracleDelay, uint256 newMaxOracleDelay);
function FRAX_USD_CHAINLINK_FEED_ADDRESS() external view returns (address);
function FRAX_USD_CHAINLINK_FEED_DECIMALS() external view returns (uint8);
function FRAX_USD_CHAINLINK_FEED_PRECISION() external view returns (uint256);
function maximumFraxUsdOracleDelay() external view returns (uint256);
function getFraxUsdChainlinkPrice()
external
view
returns (bool _isBadData, uint256 _updatedAt, uint256 _usdPerFrax);
function setMaximumFraxUsdOracleDelay(uint256 _newMaxOracleDelay) external;
}
文件 15 的 24:IPriceSource.sol
pragma solidity ^0.8.19;
import { IPriceSourceReceiver } from "./IPriceSourceReceiver.sol";
interface IPriceSource {
function addRoundData(IPriceSourceReceiver fraxOracle) external;
}
文件 16 的 24:IPriceSourceReceiver.sol
pragma solidity ^0.8.19;
interface IPriceSourceReceiver {
function addRoundData(bool isBadData, uint104 priceLow, uint104 priceHigh, uint40 timestamp) external;
function getPrices() external view returns (bool isBadData, uint256 priceLow, uint256 priceHigh);
}
文件 17 的 24:ISfrxEth.sol
pragma solidity >=0.8.19;
interface ISfrxEth {
function DOMAIN_SEPARATOR() external view returns (bytes32);
function allowance(address, address) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function asset() external view returns (address);
function balanceOf(address) external view returns (uint256);
function convertToAssets(uint256 shares) external view returns (uint256);
function convertToShares(uint256 assets) external view returns (uint256);
function decimals() external view returns (uint8);
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
function depositWithSignature(
uint256 assets,
address receiver,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 shares);
function lastRewardAmount() external view returns (uint192);
function lastSync() external view returns (uint32);
function maxDeposit(address) external view returns (uint256);
function maxMint(address) external view returns (uint256);
function maxRedeem(address owner) external view returns (uint256);
function maxWithdraw(address owner) external view returns (uint256);
function mint(uint256 shares, address receiver) external returns (uint256 assets);
function name() external view returns (string memory);
function nonces(address) external view returns (uint256);
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function previewDeposit(uint256 assets) external view returns (uint256);
function previewMint(uint256 shares) external view returns (uint256);
function previewRedeem(uint256 shares) external view returns (uint256);
function previewWithdraw(uint256 assets) external view returns (uint256);
function pricePerShare() external view returns (uint256);
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
function rewardsCycleEnd() external view returns (uint32);
function rewardsCycleLength() external view returns (uint32);
function symbol() external view returns (string memory);
function syncRewards() external;
function totalAssets() external view returns (uint256);
function totalSupply() external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
}
文件 18 的 24:IStaticOracle.sol
pragma solidity >=0.7.6 <0.9.0;
import '@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol';
interface IStaticOracle {
function UNISWAP_V3_FACTORY() external view returns (IUniswapV3Factory);
function CARDINALITY_PER_MINUTE() external view returns (uint8);
function supportedFeeTiers() external view returns (uint24[] memory);
function isPairSupported(address tokenA, address tokenB) external view returns (bool);
function getAllPoolsForPair(address tokenA, address tokenB) external view returns (address[] memory);
function quoteAllAvailablePoolsWithTimePeriod(
uint128 baseAmount,
address baseToken,
address quoteToken,
uint32 period
) external view returns (uint256 quoteAmount, address[] memory queriedPools);
function quoteSpecificFeeTiersWithTimePeriod(
uint128 baseAmount,
address baseToken,
address quoteToken,
uint24[] calldata feeTiers,
uint32 period
) external view returns (uint256 quoteAmount, address[] memory queriedPools);
function quoteSpecificPoolsWithTimePeriod(
uint128 baseAmount,
address baseToken,
address quoteToken,
address[] calldata pools,
uint32 period
) external view returns (uint256 quoteAmount);
function prepareAllAvailablePoolsWithTimePeriod(
address tokenA,
address tokenB,
uint32 period
) external returns (address[] memory preparedPools);
function prepareSpecificFeeTiersWithTimePeriod(
address tokenA,
address tokenB,
uint24[] calldata feeTiers,
uint32 period
) external returns (address[] memory preparedPools);
function prepareSpecificPoolsWithTimePeriod(address[] calldata pools, uint32 period) external;
function prepareAllAvailablePoolsWithCardinality(
address tokenA,
address tokenB,
uint16 cardinality
) external returns (address[] memory preparedPools);
function prepareSpecificFeeTiersWithCardinality(
address tokenA,
address tokenB,
uint24[] calldata feeTiers,
uint16 cardinality
) external returns (address[] memory preparedPools);
function prepareSpecificPoolsWithCardinality(address[] calldata pools, uint16 cardinality) external;
function addNewFeeTier(uint24 feeTier) external;
}
文件 19 的 24:ITimelock2Step.sol
pragma solidity 0.8.19;
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;
}
文件 20 的 24:IUniswapV3Factory.sol
pragma solidity >=0.5.0;
interface IUniswapV3Factory {
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
event PoolCreated(
address indexed token0,
address indexed token1,
uint24 indexed fee,
int24 tickSpacing,
address pool
);
event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);
function owner() external view returns (address);
function feeAmountTickSpacing(uint24 fee) external view returns (int24);
function getPool(
address tokenA,
address tokenB,
uint24 fee
) external view returns (address pool);
function createPool(
address tokenA,
address tokenB,
uint24 fee
) external returns (address pool);
function setOwner(address _owner) external;
function enableFeeAmount(uint24 fee, int24 tickSpacing) external;
}
文件 21 的 24:IUniswapV3SingleTwapOracle.sol
pragma solidity 0.8.19;
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;
}
文件 22 的 24:SfrxEthEthDualOracle.sol
pragma solidity ^0.8.19;
import { FrxEthEthDualOracle, ConstructorParams as FrxEthEthDualOracleParams } from "./FrxEthEthDualOracle.sol";
import { ISfrxEth } from "interfaces/ISfrxEth.sol";
struct ConstructorParams {
FrxEthEthDualOracleParams frxEthEthDualOracleParams;
address sfrxEthErc4626;
}
contract SfrxEthEthDualOracle is FrxEthEthDualOracle {
ISfrxEth public immutable SFRXETH_ERC4626;
constructor(ConstructorParams memory params) FrxEthEthDualOracle(params.frxEthEthDualOracleParams) {
SFRXETH_ERC4626 = ISfrxEth(params.sfrxEthErc4626);
}
function name() external view override returns (string memory _name) {
_name = "sfrxEth Dual Oracle In Eth with Curve Pool EMA and Uniswap v3 TWAP and Frax and ETH Chainlink";
}
function _calculatePrices(
uint256 ethPerFrxEthCurveEma,
uint256 fraxPerFrxEthTwap,
bool isBadDataEthUsdChainlink,
uint256 usdPerEthChainlink,
bool isBadDataFraxUsdChainlink,
uint256 usdPerFraxChainlink
) internal view override returns (bool isBadData, uint256 priceLow, uint256 priceHigh) {
(isBadData, priceLow, priceHigh) = super._calculatePrices({
ethPerFrxEthCurveEma: ethPerFrxEthCurveEma,
fraxPerFrxEthTwap: fraxPerFrxEthTwap,
isBadDataEthUsdChainlink: isBadDataEthUsdChainlink,
usdPerEthChainlink: usdPerEthChainlink,
isBadDataFraxUsdChainlink: isBadDataFraxUsdChainlink,
usdPerFraxChainlink: usdPerFraxChainlink
});
uint256 sfrxEthPricePerShare = SFRXETH_ERC4626.pricePerShare();
priceLow = (sfrxEthPricePerShare * priceLow) / ORACLE_PRECISION;
priceHigh = (sfrxEthPricePerShare * priceHigh) / ORACLE_PRECISION;
}
}
文件 23 的 24:Timelock2Step.sol
pragma solidity ^0.8.19;
abstract contract Timelock2Step {
address public pendingTimelockAddress;
address public timelockAddress;
constructor() {
timelockAddress = msg.sender;
}
error OnlyTimelock();
error OnlyPendingTimelock();
event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock);
event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock);
function _isSenderTimelock() internal view returns (bool) {
return msg.sender == timelockAddress;
}
function _requireTimelock() internal view {
if (msg.sender != timelockAddress) revert OnlyTimelock();
}
function _isSenderPendingTimelock() internal view returns (bool) {
return msg.sender == pendingTimelockAddress;
}
function _requirePendingTimelock() internal view {
if (msg.sender != pendingTimelockAddress) revert OnlyPendingTimelock();
}
function _transferTimelock(address _newTimelock) internal {
pendingTimelockAddress = _newTimelock;
emit TimelockTransferStarted(timelockAddress, _newTimelock);
}
function _acceptTransferTimelock() internal {
pendingTimelockAddress = address(0);
_setTimelock(msg.sender);
}
function _setTimelock(address _newTimelock) internal {
emit TimelockTransferred(timelockAddress, _newTimelock);
timelockAddress = _newTimelock;
}
function transferTimelock(address _newTimelock) external virtual {
_requireTimelock();
_transferTimelock(_newTimelock);
}
function acceptTransferTimelock() external virtual {
_requirePendingTimelock();
_acceptTransferTimelock();
}
function renounceTimelock() external virtual {
_requireTimelock();
_requirePendingTimelock();
_transferTimelock(address(0));
_setTimelock(address(0));
}
}
文件 24 的 24:UniswapV3SingleTwapOracle.sol
pragma solidity ^0.8.19;
import { IStaticOracle } from "@mean-finance/uniswap-v3-oracle/solidity/interfaces/IStaticOracle.sol";
import { ERC165Storage } from "@openzeppelin/contracts/utils/introspection/ERC165Storage.sol";
import { IUniswapV3SingleTwapOracle } from "interfaces/oracles/abstracts/IUniswapV3SingleTwapOracle.sol";
struct ConstructorParams {
address uniswapV3PairAddress;
uint32 twapDuration;
address baseToken;
address quoteToken;
}
abstract contract UniswapV3SingleTwapOracle is ERC165Storage, IUniswapV3SingleTwapOracle {
address public immutable UNI_V3_PAIR_ADDRESS;
uint128 public constant TWAP_PRECISION = 1e18;
address public immutable UNISWAP_V3_TWAP_BASE_TOKEN;
address public immutable UNISWAP_V3_TWAP_QUOTE_TOKEN;
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;
}
function _setTwapDuration(uint32 _newTwapDuration) internal {
emit SetTwapDuration({ oldTwapDuration: twapDuration, newTwapDuration: _newTwapDuration });
twapDuration = _newTwapDuration;
}
function setTwapDuration(uint32 _newTwapDuration) external virtual;
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
});
}
function getUniswapV3Twap() external view virtual returns (uint256 _twap) {
_twap = _getUniswapV3Twap();
}
}
{
"compilationTarget": {
"src/SfrxEthEthDualOracle.sol": "SfrxEthEthDualOracle"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": [
":@chainlink/=node_modules/@chainlink/",
":@eth-optimism/=node_modules/@eth-optimism/",
":@mean-finance/=node_modules/@mean-finance/",
":@openzeppelin/=node_modules/@openzeppelin/",
":@rari-capital/=node_modules/@rari-capital/",
":@uniswap/=node_modules/@uniswap/",
":base64-sol/=node_modules/base64-sol/",
":deploy/=deploy/",
":ds-test/=node_modules/ds-test/src/",
":forge-std/=node_modules/forge-std/src/",
":frax-standard-solidity/=node_modules/frax-standard-solidity/",
":frax-std/=node_modules/frax-standard-solidity/src/",
":hardhat/=node_modules/hardhat/",
":interfaces/=src/interfaces/",
":script/=script/",
":solidity-bytes-utils/=node_modules/solidity-bytes-utils/",
":src/=src/",
":test/=test/"
],
"viaIR": true
}
[{"inputs":[{"components":[{"components":[{"internalType":"address","name":"baseToken0","type":"address"},{"internalType":"uint8","name":"baseToken0Decimals","type":"uint8"},{"internalType":"address","name":"quoteToken0","type":"address"},{"internalType":"uint8","name":"quoteToken0Decimals","type":"uint8"},{"internalType":"address","name":"baseToken1","type":"address"},{"internalType":"uint8","name":"baseToken1Decimals","type":"uint8"},{"internalType":"address","name":"quoteToken1","type":"address"},{"internalType":"uint8","name":"quoteToken1Decimals","type":"uint8"},{"internalType":"address","name":"frxEthErc20","type":"address"},{"internalType":"address","name":"fraxErc20","type":"address"},{"internalType":"address","name":"uniV3PairAddress","type":"address"},{"internalType":"uint32","name":"twapDuration","type":"uint32"},{"internalType":"address","name":"fraxUsdChainlinkFeedAddress","type":"address"},{"internalType":"uint256","name":"fraxUsdMaximumOracleDelay","type":"uint256"},{"internalType":"address","name":"ethUsdChainlinkFeed","type":"address"},{"internalType":"uint256","name":"maxEthUsdOracleDelay","type":"uint256"},{"internalType":"address","name":"curvePoolEmaPriceOracleAddress","type":"address"},{"internalType":"uint256","name":"minimumCurvePoolEma","type":"uint256"},{"internalType":"uint256","name":"maximumCurvePoolEma","type":"uint256"},{"internalType":"address","name":"timelockAddress","type":"address"}],"internalType":"struct ConstructorParams","name":"frxEthEthDualOracleParams","type":"tuple"},{"internalType":"address","name":"sfrxEthErc4626","type":"address"}],"internalType":"struct ConstructorParams","name":"params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"OnlyPendingTimelock","type":"error"},{"inputs":[],"name":"OnlyTimelock","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMaximum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaximum","type":"uint256"}],"name":"SetMaximumCurvePoolEma","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":false,"internalType":"uint256","name":"oldMaxOracleDelay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMaxOracleDelay","type":"uint256"}],"name":"SetMaximumFraxUsdOracleDelay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinimum","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinimum","type":"uint256"}],"name":"SetMinimumCurvePoolEma","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldTwapDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTwapDuration","type":"uint256"}],"name":"SetTwapDuration","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":"CURVE_POOL_EMA_PRICE_ORACLE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CURVE_POOL_EMA_PRICE_ORACLE_PRECISION","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":"FRAX_USD_CHAINLINK_FEED_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRAX_USD_CHAINLINK_FEED_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FRAX_USD_CHAINLINK_FEED_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"SFRXETH_ERC4626","outputs":[{"internalType":"contract ISfrxEth","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TWAP_PRECISION","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNISWAP_V3_TWAP_BASE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNISWAP_V3_TWAP_QUOTE_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNI_V3_PAIR_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptTransferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPriceSourceReceiver","name":"fraxOracle","type":"address"}],"name":"addRoundData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethPerFrxEthCurveEma","type":"uint256"},{"internalType":"uint256","name":"fraxPerFrxEthTwap","type":"uint256"},{"internalType":"bool","name":"isBadDataEthUsdChainlink","type":"bool"},{"internalType":"uint256","name":"usdPerEthChainlink","type":"uint256"},{"internalType":"bool","name":"isBadDataFraxUsdChainlink","type":"bool"},{"internalType":"uint256","name":"usdPerFraxChainlink","type":"uint256"}],"name":"calculatePrices","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":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainlinkUsdPerFrax","outputs":[{"internalType":"bool","name":"isBadData","type":"bool"},{"internalType":"uint256","name":"usdPerFrax","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurveEmaEthPerFrxEth","outputs":[{"internalType":"uint256","name":"ethPerFrxEth","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurvePoolToken1EmaPrice","outputs":[{"internalType":"uint256","name":"_emaPrice","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":"getFraxUsdChainlinkPrice","outputs":[{"internalType":"bool","name":"_isBadData","type":"bool"},{"internalType":"uint256","name":"_updatedAt","type":"uint256"},{"internalType":"uint256","name":"_usdPerFrax","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":"getUniswapV3Twap","outputs":[{"internalType":"uint256","name":"_twap","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUsdPerEthChainlink","outputs":[{"internalType":"bool","name":"isBadData","type":"bool"},{"internalType":"uint256","name":"usdPerEth","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumCurvePoolEma","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumEthUsdOracleDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maximumFraxUsdOracleDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumCurvePoolEma","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"_name","type":"string"}],"stateMutability":"view","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":"maximumPrice","type":"uint256"}],"name":"setMaximumCurvePoolEma","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxOracleDelay","type":"uint256"}],"name":"setMaximumEthUsdOracleDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxOracleDelay","type":"uint256"}],"name":"setMaximumFraxUsdOracleDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minimumPrice","type":"uint256"}],"name":"setMinimumCurvePoolEma","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newTwapDuration","type":"uint32"}],"name":"setTwapDuration","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"}]