Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
FxETHTwapOracle
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
import { Math } from "@openzeppelin/contracts/math/Math.sol";
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
import { ITwapOracle } from "../../price-oracle/interfaces/ITwapOracle.sol";
import { ICurvePoolOracle } from "../../interfaces/ICurvePoolOracle.sol";
import { IFxPriceOracle } from "../interfaces/IFxPriceOracle.sol";
// solhint-disable var-name-mixedcase
contract FxETHTwapOracle is IFxPriceOracle {
using SafeMath for uint256;
/*************
* Constants *
*************/
/// @dev The precison use to calculation.
uint256 private constant PRECISION = 1e18;
/// @notice The address of chainlink stETH/USD twap oracle.
address public immutable chainlinkStETHTwapOracle;
/// @notice The address of chainlink ETH/USD twap oracle.
address public immutable chainlinkETHTwapOracle;
/// @notice The address of curve ETH/stETH pool.
address public immutable curvePool;
/***********
* Structs *
***********/
struct CachedPrice {
uint256 ETH_USDPrice;
uint256 stETH_USDPrice;
uint256 stETH_ETHPrice;
}
/***************
* Constructor *
***************/
constructor(
address _chainlinkStETHTwapOracle,
address _chainlinkETHTwapOracle,
address _curvePool
) {
chainlinkStETHTwapOracle = _chainlinkStETHTwapOracle;
chainlinkETHTwapOracle = _chainlinkETHTwapOracle;
curvePool = _curvePool;
}
/*************************
* Public View Functions *
*************************/
/// @inheritdoc IFxPriceOracle
function getPrice()
external
view
override
returns (
bool _isValid,
uint256 _safePrice,
uint256 _minUnsafePrice,
uint256 _maxUnsafePrice
)
{
CachedPrice memory _cached = _fetchPrice();
_isValid = _isPriceValid(_cached);
_safePrice = _cached.stETH_USDPrice;
_minUnsafePrice = Math.min(_cached.ETH_USDPrice, _cached.stETH_USDPrice);
_maxUnsafePrice = Math.max(_cached.ETH_USDPrice, _cached.stETH_USDPrice);
if (_cached.stETH_ETHPrice != 0) {
uint256 _curveStETHPrice = _cached.ETH_USDPrice.mul(_cached.stETH_ETHPrice) / PRECISION;
if (_curveStETHPrice < _minUnsafePrice) {
_minUnsafePrice = _curveStETHPrice;
}
if (_curveStETHPrice > _maxUnsafePrice) {
_maxUnsafePrice = _curveStETHPrice;
}
}
}
/**********************
* Internal Functions *
**********************/
function _fetchPrice() internal view returns (CachedPrice memory _cached) {
_cached.ETH_USDPrice = ITwapOracle(chainlinkETHTwapOracle).getTwap(block.timestamp);
_cached.stETH_USDPrice = ITwapOracle(chainlinkStETHTwapOracle).getTwap(block.timestamp);
if (curvePool != address(0)) {
_cached.stETH_ETHPrice = ICurvePoolOracle(curvePool).ema_price();
}
}
function _isPriceValid(CachedPrice memory _cached) internal pure returns (bool) {
uint256 priceDiff;
if (_cached.ETH_USDPrice > _cached.stETH_USDPrice) {
priceDiff = _cached.ETH_USDPrice - _cached.stETH_USDPrice;
} else {
priceDiff = _cached.stETH_USDPrice - _cached.ETH_USDPrice;
}
// |eth_usd_price - steth_usd_price| / steth_usd_price < 1%
if (priceDiff * 100 >= _cached.stETH_USDPrice) return false;
if (_cached.stETH_ETHPrice > 0) {
return 0.99 ether <= _cached.stETH_ETHPrice && _cached.stETH_ETHPrice <= 1.01 ether;
} else {
return true;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow, so we distribute
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
interface IFxPriceOracle {
/// @notice Return the oracle price with 18 decimal places.
/// @return isValid Whether the oracle is valid.
/// @return safePrice The safe oracle price when the oracle is valid.
/// @return minUnsafePrice The minimum unsafe oracle price when the oracle is invalid.
/// @return maxUnsafePrice The maximum unsafe oracle price when the oracle is invalid.
function getPrice()
external
view
returns (
bool isValid,
uint256 safePrice,
uint256 minUnsafePrice,
uint256 maxUnsafePrice
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
// solhint-disable func-name-mixedcase
interface ICurvePoolOracle {
function last_price() external view returns (uint256);
function ema_price() external view returns (uint256);
function ma_exp_time() external view returns (uint256);
function ma_last_time() external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.7.6;
interface ITwapOracle {
/// @notice Return TWAP with 18 decimal places in the epoch ending at the specified timestamp.
/// Zero is returned if TWAP in the epoch is not available.
/// @param timestamp End Timestamp in seconds of the epoch
/// @return TWAP (18 decimal places) in the epoch, or zero if not available
function getTwap(uint256 timestamp) external view returns (uint256);
/// @notice Return the latest price with 18 decimal places.
function getLatest() external view returns (uint256);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_chainlinkStETHTwapOracle","type":"address"},{"internalType":"address","name":"_chainlinkETHTwapOracle","type":"address"},{"internalType":"address","name":"_curvePool","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"chainlinkETHTwapOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainlinkStETHTwapOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"curvePool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrice","outputs":[{"internalType":"bool","name":"_isValid","type":"bool"},{"internalType":"uint256","name":"_safePrice","type":"uint256"},{"internalType":"uint256","name":"_minUnsafePrice","type":"uint256"},{"internalType":"uint256","name":"_maxUnsafePrice","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60e060405234801561001057600080fd5b506040516105d53803806105d58339818101604052606081101561003357600080fd5b50805160208201516040909201516001600160601b0319606092831b811660805292821b831660a052901b1660c05260805160601c60a05160601c60c05160601c61052d6100a86000398060b752806102ef528061031e52508060db52806101c652508060ff5280610276525061052d6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063218751b214610051578063262ce9061461007557806335dcffbd1461007d57806398d5fdca14610085575b600080fd5b6100596100b5565b604080516001600160a01b039092168252519081900360200190f35b6100596100d9565b6100596100fd565b61008d610121565b6040805194151585526020850193909352838301919091526060830152519081900360800190f35b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b60008060008060006101316101bc565b905061013c816103aa565b6020820151825191965094506101529085610432565b92506101668160000151826020015161044c565b915080604001516000146101b55760408101518151600091670de0b6b3a7640000916101919161045c565b8161019857fe5b049050838110156101a7578093505b828111156101b3578092505b505b5090919293565b6101c46104b5565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639f057151426040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561022857600080fd5b505afa15801561023c573d6000803e3d6000fd5b505050506040513d602081101561025257600080fd5b5051815260408051639f05715160e01b815242600482015290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691639f057151916024808301926020929190829003018186803b1580156102bc57600080fd5b505afa1580156102d0573d6000803e3d6000fd5b505050506040513d60208110156102e657600080fd5b505160208201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316156103a7577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c24c7c296040518163ffffffff1660e01b815260040160206040518083038186803b15801561037557600080fd5b505afa158015610389573d6000803e3d6000fd5b505050506040513d602081101561039f57600080fd5b505160408201525b90565b6000808260200151836000015111156103cb575060208201518251036103d5565b5081516020830151035b826020015181606402106103ed57600091505061042d565b604083015115610427578260400151670dbd2fc137a300001115801561041f5750670e043da617250000836040015111155b91505061042d565b60019150505b919050565b60008183106104415781610443565b825b90505b92915050565b6000818310156104415781610443565b60008261046b57506000610446565b8282028284828161047857fe5b04146104435760405162461bcd60e51b81526004018080602001828103825260218152602001806104d76021913960400191505060405180910390fd5b6040518060600160405280600081526020016000815260200160008152509056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220b6afa81b4028e0b1d33fbc905033e59ec8ac61f8849c1aef21bd3bb57d91e2ab64736f6c63430007060033000000000000000000000000d24ac180e6769fd5f624e7605b93084171074a77000000000000000000000000460b3cde57dfba90dbed02fd83d3990a92da123000000000000000000000000021e27a5e5513d6e65c4f830167390997aa84843a
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061004c5760003560e01c8063218751b214610051578063262ce9061461007557806335dcffbd1461007d57806398d5fdca14610085575b600080fd5b6100596100b5565b604080516001600160a01b039092168252519081900360200190f35b6100596100d9565b6100596100fd565b61008d610121565b6040805194151585526020850193909352838301919091526060830152519081900360800190f35b7f00000000000000000000000021e27a5e5513d6e65c4f830167390997aa84843a81565b7f000000000000000000000000460b3cde57dfba90dbed02fd83d3990a92da123081565b7f000000000000000000000000d24ac180e6769fd5f624e7605b93084171074a7781565b60008060008060006101316101bc565b905061013c816103aa565b6020820151825191965094506101529085610432565b92506101668160000151826020015161044c565b915080604001516000146101b55760408101518151600091670de0b6b3a7640000916101919161045c565b8161019857fe5b049050838110156101a7578093505b828111156101b3578092505b505b5090919293565b6101c46104b5565b7f000000000000000000000000460b3cde57dfba90dbed02fd83d3990a92da12306001600160a01b0316639f057151426040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561022857600080fd5b505afa15801561023c573d6000803e3d6000fd5b505050506040513d602081101561025257600080fd5b5051815260408051639f05715160e01b815242600482015290516001600160a01b037f000000000000000000000000d24ac180e6769fd5f624e7605b93084171074a771691639f057151916024808301926020929190829003018186803b1580156102bc57600080fd5b505afa1580156102d0573d6000803e3d6000fd5b505050506040513d60208110156102e657600080fd5b505160208201527f00000000000000000000000021e27a5e5513d6e65c4f830167390997aa84843a6001600160a01b0316156103a7577f00000000000000000000000021e27a5e5513d6e65c4f830167390997aa84843a6001600160a01b031663c24c7c296040518163ffffffff1660e01b815260040160206040518083038186803b15801561037557600080fd5b505afa158015610389573d6000803e3d6000fd5b505050506040513d602081101561039f57600080fd5b505160408201525b90565b6000808260200151836000015111156103cb575060208201518251036103d5565b5081516020830151035b826020015181606402106103ed57600091505061042d565b604083015115610427578260400151670dbd2fc137a300001115801561041f5750670e043da617250000836040015111155b91505061042d565b60019150505b919050565b60008183106104415781610443565b825b90505b92915050565b6000818310156104415781610443565b60008261046b57506000610446565b8282028284828161047857fe5b04146104435760405162461bcd60e51b81526004018080602001828103825260218152602001806104d76021913960400191505060405180910390fd5b6040518060600160405280600081526020016000815260200160008152509056fe536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220b6afa81b4028e0b1d33fbc905033e59ec8ac61f8849c1aef21bd3bb57d91e2ab64736f6c63430007060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000d24ac180e6769fd5f624e7605b93084171074a77000000000000000000000000460b3cde57dfba90dbed02fd83d3990a92da123000000000000000000000000021e27a5e5513d6e65c4f830167390997aa84843a
-----Decoded View---------------
Arg [0] : _chainlinkStETHTwapOracle (address): 0xD24AC180e6769Fd5F624e7605B93084171074A77
Arg [1] : _chainlinkETHTwapOracle (address): 0x460B3CdE57DfbA90DBed02fd83d3990a92DA1230
Arg [2] : _curvePool (address): 0x21E27a5E5513D6e65C4f830167390997aA84843a
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000d24ac180e6769fd5f624e7605b93084171074a77
Arg [1] : 000000000000000000000000460b3cde57dfba90dbed02fd83d3990a92da1230
Arg [2] : 00000000000000000000000021e27a5e5513d6e65c4f830167390997aa84843a
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
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.