Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 5 from a total of 5 transactions
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
OETHOracleRouter
Compiler Version
v0.8.7+commit.e28d00a7
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.8.0;
import "../interfaces/chainlink/AggregatorV3Interface.sol";
import { IOracle } from "../interfaces/IOracle.sol";
import { Helpers } from "../utils/Helpers.sol";
import { StableMath } from "../utils/StableMath.sol";
import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol";
// @notice Abstract functionality that is shared between various Oracle Routers
abstract contract OracleRouterBase is IOracle {
using StableMath for uint256;
using SafeCast for int256;
uint256 internal constant MIN_DRIFT = 0.7e18;
uint256 internal constant MAX_DRIFT = 1.3e18;
address internal constant FIXED_PRICE =
0x0000000000000000000000000000000000000001;
// Maximum allowed staleness buffer above normal Oracle maximum staleness
uint256 internal constant STALENESS_BUFFER = 1 days;
mapping(address => uint8) internal decimalsCache;
/**
* @dev The price feed contract to use for a particular asset along with
* maximum data staleness
* @param asset address of the asset
* @return feedAddress address of the price feed for the asset
* @return maxStaleness maximum acceptable data staleness duration
*/
function feedMetadata(address asset)
internal
view
virtual
returns (address feedAddress, uint256 maxStaleness);
/**
* @notice Returns the total price in 18 digit unit for a given asset.
* @param asset address of the asset
* @return uint256 unit price for 1 asset unit, in 18 decimal fixed
*/
function price(address asset)
external
view
virtual
override
returns (uint256)
{
(address _feed, uint256 maxStaleness) = feedMetadata(asset);
require(_feed != address(0), "Asset not available");
require(_feed != FIXED_PRICE, "Fixed price feeds not supported");
(, int256 _iprice, , uint256 updatedAt, ) = AggregatorV3Interface(_feed)
.latestRoundData();
require(
updatedAt + maxStaleness >= block.timestamp,
"Oracle price too old"
);
uint8 decimals = getDecimals(_feed);
uint256 _price = _iprice.toUint256().scaleBy(18, decimals);
if (shouldBePegged(asset)) {
require(_price <= MAX_DRIFT, "Oracle: Price exceeds max");
require(_price >= MIN_DRIFT, "Oracle: Price under min");
}
return _price;
}
function getDecimals(address _feed) internal view virtual returns (uint8) {
uint8 decimals = decimalsCache[_feed];
require(decimals > 0, "Oracle: Decimals not cached");
return decimals;
}
/**
* @notice Before an asset/feed price is fetches for the first time the
* decimals need to be cached. This is a gas optimization
* @param asset address of the asset
* @return uint8 corresponding asset decimals
*/
function cacheDecimals(address asset) external returns (uint8) {
(address _feed, ) = feedMetadata(asset);
require(_feed != address(0), "Asset not available");
require(_feed != FIXED_PRICE, "Fixed price feeds not supported");
uint8 decimals = AggregatorV3Interface(_feed).decimals();
decimalsCache[_feed] = decimals;
return decimals;
}
function shouldBePegged(address _asset) internal view returns (bool) {
string memory symbol = Helpers.getSymbol(_asset);
bytes32 symbolHash = keccak256(abi.encodePacked(symbol));
return
symbolHash == keccak256(abi.encodePacked("DAI")) ||
symbolHash == keccak256(abi.encodePacked("USDC")) ||
symbolHash == keccak256(abi.encodePacked("USDT"));
}
}
// @notice Oracle Router that denominates all prices in USD
contract OracleRouter is OracleRouterBase {
/**
* @dev The price feed contract to use for a particular asset along with
* maximum data staleness
* @param asset address of the asset
* @return feedAddress address of the price feed for the asset
* @return maxStaleness maximum acceptable data staleness duration
*/
function feedMetadata(address asset)
internal
pure
virtual
override
returns (address feedAddress, uint256 maxStaleness)
{
/* + STALENESS_BUFFER is added in case Oracle for some reason doesn't
* update on heartbeat and we add a generous buffer amount.
*/
if (asset == 0x6B175474E89094C44Da98b954EedeAC495271d0F) {
// https://data.chain.link/ethereum/mainnet/stablecoins/dai-usd
// Chainlink: DAI/USD
feedAddress = 0xAed0c38402a5d19df6E4c03F4E2DceD6e29c1ee9;
maxStaleness = 1 hours + STALENESS_BUFFER;
} else if (asset == 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48) {
// https://data.chain.link/ethereum/mainnet/stablecoins/usdc-usd
// Chainlink: USDC/USD
feedAddress = 0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6;
maxStaleness = 1 days + STALENESS_BUFFER;
} else if (asset == 0xdAC17F958D2ee523a2206206994597C13D831ec7) {
// https://data.chain.link/ethereum/mainnet/stablecoins/usdt-usd
// Chainlink: USDT/USD
feedAddress = 0x3E7d1eAB13ad0104d2750B8863b489D65364e32D;
maxStaleness = 1 days + STALENESS_BUFFER;
} else if (asset == 0xc00e94Cb662C3520282E6f5717214004A7f26888) {
// https://data.chain.link/ethereum/mainnet/crypto-usd/comp-usd
// Chainlink: COMP/USD
feedAddress = 0xdbd020CAeF83eFd542f4De03e3cF0C28A4428bd5;
maxStaleness = 1 hours + STALENESS_BUFFER;
} else if (asset == 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9) {
// https://data.chain.link/ethereum/mainnet/crypto-usd/aave-usd
// Chainlink: AAVE/USD
feedAddress = 0x547a514d5e3769680Ce22B2361c10Ea13619e8a9;
maxStaleness = 1 hours + STALENESS_BUFFER;
} else if (asset == 0xD533a949740bb3306d119CC777fa900bA034cd52) {
// https://data.chain.link/ethereum/mainnet/crypto-usd/crv-usd
// Chainlink: CRV/USD
feedAddress = 0xCd627aA160A6fA45Eb793D19Ef54f5062F20f33f;
maxStaleness = 1 days + STALENESS_BUFFER;
} else if (asset == 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B) {
// Chainlink: CVX/USD
feedAddress = 0xd962fC30A72A84cE50161031391756Bf2876Af5D;
maxStaleness = 1 days + STALENESS_BUFFER;
} else {
revert("Asset not available");
}
}
}
// @notice Oracle Router that denominates all prices in ETH
contract OETHOracleRouter is OracleRouter {
using StableMath for uint256;
/**
* @notice Returns the total price in 18 digit units for a given asset.
* This implementation does not (!) do range checks as the
* parent OracleRouter does.
* @param asset address of the asset
* @return uint256 unit price for 1 asset unit, in 18 decimal fixed
*/
function price(address asset)
external
view
virtual
override
returns (uint256)
{
(address _feed, uint256 maxStaleness) = feedMetadata(asset);
if (_feed == FIXED_PRICE) {
return 1e18;
}
require(_feed != address(0), "Asset not available");
(, int256 _iprice, , uint256 updatedAt, ) = AggregatorV3Interface(_feed)
.latestRoundData();
require(
updatedAt + maxStaleness >= block.timestamp,
"Oracle price too old"
);
uint8 decimals = getDecimals(_feed);
uint256 _price = uint256(_iprice).scaleBy(18, decimals);
return _price;
}
/**
* @dev The price feed contract to use for a particular asset along with
* maximum data staleness
* @param asset address of the asset
* @return feedAddress address of the price feed for the asset
* @return maxStaleness maximum acceptable data staleness duration
*/
function feedMetadata(address asset)
internal
pure
virtual
override
returns (address feedAddress, uint256 maxStaleness)
{
if (asset == 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2) {
// FIXED_PRICE: WETH/ETH
feedAddress = FIXED_PRICE;
maxStaleness = 0;
} else if (asset == 0x5E8422345238F34275888049021821E8E08CAa1f) {
// frxETH/ETH
feedAddress = 0xC58F3385FBc1C8AD2c0C9a061D7c13b141D7A5Df;
maxStaleness = 18 hours + STALENESS_BUFFER;
} else if (asset == 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84) {
// https://data.chain.link/ethereum/mainnet/crypto-eth/steth-eth
// Chainlink: stETH/ETH
feedAddress = 0x86392dC19c0b719886221c78AB11eb8Cf5c52812;
maxStaleness = 1 days + STALENESS_BUFFER;
} else if (asset == 0xae78736Cd615f374D3085123A210448E74Fc6393) {
// https://data.chain.link/ethereum/mainnet/crypto-eth/reth-eth
// Chainlink: rETH/ETH
feedAddress = 0x536218f9E9Eb48863970252233c8F271f554C2d0;
maxStaleness = 1 days + STALENESS_BUFFER;
} else if (asset == 0xD533a949740bb3306d119CC777fa900bA034cd52) {
// https://data.chain.link/ethereum/mainnet/crypto-eth/crv-eth
// Chainlink: CRV/ETH
feedAddress = 0x8a12Be339B0cD1829b91Adc01977caa5E9ac121e;
maxStaleness = 1 days + STALENESS_BUFFER;
} else if (asset == 0x4e3FBD56CD56c3e72c1403e103b45Db9da5B9D2B) {
// https://data.chain.link/ethereum/mainnet/crypto-eth/cvx-eth
// Chainlink: CVX/ETH
feedAddress = 0xC9CbF687f43176B302F03f5e58470b77D07c61c6;
maxStaleness = 1 days + STALENESS_BUFFER;
} else if (asset == 0xBe9895146f7AF43049ca1c1AE358B0541Ea49704) {
// https://data.chain.link/ethereum/mainnet/crypto-eth/cbeth-eth
// Chainlink: cbETH/ETH
feedAddress = 0xF017fcB346A1885194689bA23Eff2fE6fA5C483b;
maxStaleness = 1 days + STALENESS_BUFFER;
} else {
revert("Asset not available");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)
pragma solidity ^0.8.0;
/**
* @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such 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.
*
* Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
* all math on `uint256` and `int256` and then downcasting.
*/
library SafeCast {
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*
* _Available since v3.1._
*/
function toInt128(int256 value) internal pure returns (int128) {
require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*
* _Available since v3.1._
*/
function toInt64(int256 value) internal pure returns (int64) {
require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*
* _Available since v3.1._
*/
function toInt32(int256 value) internal pure returns (int32) {
require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*
* _Available since v3.1._
*/
function toInt16(int256 value) internal pure returns (int16) {
require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*
* _Available since v3.1._
*/
function toInt8(int256 value) internal pure returns (int8) {
require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
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) {
unchecked {
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) {
unchecked {
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) {
unchecked {
// 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) {
unchecked {
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) {
unchecked {
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) {
return a + b;
}
/**
* @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) {
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) {
return a * b;
}
/**
* @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.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
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) {
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) {
unchecked {
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.
*
* 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) {
unchecked {
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) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}// 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);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
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
pragma solidity ^0.8.0;
interface IBasicToken {
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOracle {
/**
* @dev returns the asset price in USD, in 8 decimal digits.
*
* The version of priceProvider deployed for OETH has 18 decimal digits
*/
function price(address asset) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IBasicToken } from "../interfaces/IBasicToken.sol";
library Helpers {
/**
* @notice Fetch the `symbol()` from an ERC20 token
* @dev Grabs the `symbol()` from a contract
* @param _token Address of the ERC20 token
* @return string Symbol of the ERC20 token
*/
function getSymbol(address _token) internal view returns (string memory) {
string memory symbol = IBasicToken(_token).symbol();
return symbol;
}
/**
* @notice Fetch the `decimals()` from an ERC20 token
* @dev Grabs the `decimals()` from a contract and fails if
* the decimal value does not live within a certain range
* @param _token Address of the ERC20 token
* @return uint256 Decimals of the ERC20 token
*/
function getDecimals(address _token) internal view returns (uint256) {
uint256 decimals = IBasicToken(_token).decimals();
require(
decimals >= 4 && decimals <= 18,
"Token must have sufficient decimal places"
);
return decimals;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { SafeMath } from "@openzeppelin/contracts/utils/math/SafeMath.sol";
// Based on StableMath from Stability Labs Pty. Ltd.
// https://github.com/mstable/mStable-contracts/blob/master/contracts/shared/StableMath.sol
library StableMath {
using SafeMath for uint256;
/**
* @dev Scaling unit for use in specific calculations,
* where 1 * 10**18, or 1e18 represents a unit '1'
*/
uint256 private constant FULL_SCALE = 1e18;
/***************************************
Helpers
****************************************/
/**
* @dev Adjust the scale of an integer
* @param to Decimals to scale to
* @param from Decimals to scale from
*/
function scaleBy(
uint256 x,
uint256 to,
uint256 from
) internal pure returns (uint256) {
if (to > from) {
x = x.mul(10**(to - from));
} else if (to < from) {
// slither-disable-next-line divide-before-multiply
x = x.div(10**(from - to));
}
return x;
}
/***************************************
Precise Arithmetic
****************************************/
/**
* @dev Multiplies two precise units, and then truncates by the full scale
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit
*/
function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {
return mulTruncateScale(x, y, FULL_SCALE);
}
/**
* @dev Multiplies two precise units, and then truncates by the given scale. For example,
* when calculating 90% of 10e18, (10e18 * 9e17) / 1e18 = (9e36) / 1e18 = 9e18
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @param scale Scale unit
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit
*/
function mulTruncateScale(
uint256 x,
uint256 y,
uint256 scale
) internal pure returns (uint256) {
// e.g. assume scale = fullScale
// z = 10e18 * 9e17 = 9e36
uint256 z = x.mul(y);
// return 9e36 / 1e18 = 9e18
return z.div(scale);
}
/**
* @dev Multiplies two precise units, and then truncates by the full scale, rounding up the result
* @param x Left hand input to multiplication
* @param y Right hand input to multiplication
* @return Result after multiplying the two inputs and then dividing by the shared
* scale unit, rounded up to the closest base unit.
*/
function mulTruncateCeil(uint256 x, uint256 y)
internal
pure
returns (uint256)
{
// e.g. 8e17 * 17268172638 = 138145381104e17
uint256 scaled = x.mul(y);
// e.g. 138145381104e17 + 9.99...e17 = 138145381113.99...e17
uint256 ceil = scaled.add(FULL_SCALE.sub(1));
// e.g. 13814538111.399...e18 / 1e18 = 13814538111
return ceil.div(FULL_SCALE);
}
/**
* @dev Precisely divides two units, by first scaling the left hand operand. Useful
* for finding percentage weightings, i.e. 8e18/10e18 = 80% (or 8e17)
* @param x Left hand input to division
* @param y Right hand input to division
* @return Result after multiplying the left operand by the scale, and
* executing the division on the right hand input.
*/
function divPrecisely(uint256 x, uint256 y)
internal
pure
returns (uint256)
{
// e.g. 8e18 * 1e18 = 8e36
uint256 z = x.mul(FULL_SCALE);
// e.g. 8e36 / 10e18 = 8e17
return z.div(y);
}
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"cacheDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5061089c806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806336b6d9441461003b578063aea9107814610065575b600080fd5b61004e61004936600461062c565b610086565b60405160ff90911681526020015b60405180910390f35b61007861007336600461062c565b6101bf565b60405190815260200161005c565b60008061009283610312565b5090506001600160a01b0381166100c45760405162461bcd60e51b81526004016100bb906106c8565b60405180910390fd5b6001600160a01b0381166001141561011e5760405162461bcd60e51b815260206004820152601f60248201527f4669786564207072696365206665656473206e6f7420737570706f727465640060448201526064016100bb565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561015957600080fd5b505afa15801561016d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019191906106a5565b6001600160a01b03929092166000908152602081905260409020805460ff191660ff84161790555092915050565b60008060006101cd84610312565b90925090506001600160a01b038216600114156101f55750670de0b6b3a76400009392505050565b6001600160a01b03821661021b5760405162461bcd60e51b81526004016100bb906106c8565b600080836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561025757600080fd5b505afa15801561026b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028f9190610655565b509350509250504283826102a391906106f5565b10156102e85760405162461bcd60e51b815260206004820152601460248201527313dc9858db19481c1c9a58d9481d1bdbc81bdb1960621b60448201526064016100bb565b60006102f38561051d565b9050600061030684601260ff851661058c565b98975050505050505050565b60008073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b03841614156103465750600190506000915091565b735e8422345238f34275888049021821e8e08caa1f6001600160a01b03841614156103985773c58f3385fbc1c8ad2c0c9a061d7c13b141d7a5df91506103916201518061fd206106f5565b9050915091565b73ae7ab96520de3a18e5e111b5eaab095312d7fe846001600160a01b03841614156103e1577386392dc19c0b719886221c78ab11eb8cf5c52812915061039162015180806106f5565b73ae78736cd615f374d3085123a210448e74fc63936001600160a01b038416141561042a5773536218f9e9eb48863970252233c8f271f554c2d0915061039162015180806106f5565b73d533a949740bb3306d119cc777fa900ba034cd526001600160a01b038416141561047357738a12be339b0cd1829b91adc01977caa5e9ac121e915061039162015180806106f5565b734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b03841614156104bc5773c9cbf687f43176b302f03f5e58470b77d07c61c6915061039162015180806106f5565b73be9895146f7af43049ca1c1ae358b0541ea497046001600160a01b03841614156105055773f017fcb346a1885194689ba23eff2fe6fa5c483b915061039162015180806106f5565b60405162461bcd60e51b81526004016100bb906106c8565b6001600160a01b03811660009081526020819052604081205460ff16806105865760405162461bcd60e51b815260206004820152601b60248201527f4f7261636c653a20446563696d616c73206e6f7420636163686564000000000060448201526064016100bb565b92915050565b6000818311156105bc576105b56105a38385610839565b6105ae90600a610772565b85906105ee565b93506105e6565b818310156105e6576105e36105d18484610839565b6105dc90600a610772565b8590610601565b93505b509192915050565b60006105fa828461081a565b9392505050565b60006105fa828461070d565b805169ffffffffffffffffffff8116811461062757600080fd5b919050565b60006020828403121561063e57600080fd5b81356001600160a01b03811681146105fa57600080fd5b600080600080600060a0868803121561066d57600080fd5b6106768661060d565b94506020860151935060408601519250606086015191506106996080870161060d565b90509295509295909350565b6000602082840312156106b757600080fd5b815160ff811681146105fa57600080fd5b6020808252601390820152724173736574206e6f7420617661696c61626c6560681b604082015260600190565b6000821982111561070857610708610850565b500190565b60008261072a57634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111561076a57816000190482111561075057610750610850565b8085161561075d57918102915b93841c9390800290610734565b509250929050565b60006105fa838360008261078857506001610586565b8161079557506000610586565b81600181146107ab57600281146107b5576107d1565b6001915050610586565b60ff8411156107c6576107c6610850565b50506001821b610586565b5060208310610133831016604e8410600b84101617156107f4575081810a610586565b6107fe838361072f565b806000190482111561081257610812610850565b029392505050565b600081600019048311821515161561083457610834610850565b500290565b60008282101561084b5761084b610850565b500390565b634e487b7160e01b600052601160045260246000fdfea2646970667358221220b66fc794fbca0536355abd67a782ac6a9194aaf7601c2523f308f0dd208ba4a664736f6c63430008070033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100365760003560e01c806336b6d9441461003b578063aea9107814610065575b600080fd5b61004e61004936600461062c565b610086565b60405160ff90911681526020015b60405180910390f35b61007861007336600461062c565b6101bf565b60405190815260200161005c565b60008061009283610312565b5090506001600160a01b0381166100c45760405162461bcd60e51b81526004016100bb906106c8565b60405180910390fd5b6001600160a01b0381166001141561011e5760405162461bcd60e51b815260206004820152601f60248201527f4669786564207072696365206665656473206e6f7420737570706f727465640060448201526064016100bb565b6000816001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561015957600080fd5b505afa15801561016d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061019191906106a5565b6001600160a01b03929092166000908152602081905260409020805460ff191660ff84161790555092915050565b60008060006101cd84610312565b90925090506001600160a01b038216600114156101f55750670de0b6b3a76400009392505050565b6001600160a01b03821661021b5760405162461bcd60e51b81526004016100bb906106c8565b600080836001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a06040518083038186803b15801561025757600080fd5b505afa15801561026b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061028f9190610655565b509350509250504283826102a391906106f5565b10156102e85760405162461bcd60e51b815260206004820152601460248201527313dc9858db19481c1c9a58d9481d1bdbc81bdb1960621b60448201526064016100bb565b60006102f38561051d565b9050600061030684601260ff851661058c565b98975050505050505050565b60008073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b03841614156103465750600190506000915091565b735e8422345238f34275888049021821e8e08caa1f6001600160a01b03841614156103985773c58f3385fbc1c8ad2c0c9a061d7c13b141d7a5df91506103916201518061fd206106f5565b9050915091565b73ae7ab96520de3a18e5e111b5eaab095312d7fe846001600160a01b03841614156103e1577386392dc19c0b719886221c78ab11eb8cf5c52812915061039162015180806106f5565b73ae78736cd615f374d3085123a210448e74fc63936001600160a01b038416141561042a5773536218f9e9eb48863970252233c8f271f554c2d0915061039162015180806106f5565b73d533a949740bb3306d119cc777fa900ba034cd526001600160a01b038416141561047357738a12be339b0cd1829b91adc01977caa5e9ac121e915061039162015180806106f5565b734e3fbd56cd56c3e72c1403e103b45db9da5b9d2b6001600160a01b03841614156104bc5773c9cbf687f43176b302f03f5e58470b77d07c61c6915061039162015180806106f5565b73be9895146f7af43049ca1c1ae358b0541ea497046001600160a01b03841614156105055773f017fcb346a1885194689ba23eff2fe6fa5c483b915061039162015180806106f5565b60405162461bcd60e51b81526004016100bb906106c8565b6001600160a01b03811660009081526020819052604081205460ff16806105865760405162461bcd60e51b815260206004820152601b60248201527f4f7261636c653a20446563696d616c73206e6f7420636163686564000000000060448201526064016100bb565b92915050565b6000818311156105bc576105b56105a38385610839565b6105ae90600a610772565b85906105ee565b93506105e6565b818310156105e6576105e36105d18484610839565b6105dc90600a610772565b8590610601565b93505b509192915050565b60006105fa828461081a565b9392505050565b60006105fa828461070d565b805169ffffffffffffffffffff8116811461062757600080fd5b919050565b60006020828403121561063e57600080fd5b81356001600160a01b03811681146105fa57600080fd5b600080600080600060a0868803121561066d57600080fd5b6106768661060d565b94506020860151935060408601519250606086015191506106996080870161060d565b90509295509295909350565b6000602082840312156106b757600080fd5b815160ff811681146105fa57600080fd5b6020808252601390820152724173736574206e6f7420617661696c61626c6560681b604082015260600190565b6000821982111561070857610708610850565b500190565b60008261072a57634e487b7160e01b600052601260045260246000fd5b500490565b600181815b8085111561076a57816000190482111561075057610750610850565b8085161561075d57918102915b93841c9390800290610734565b509250929050565b60006105fa838360008261078857506001610586565b8161079557506000610586565b81600181146107ab57600281146107b5576107d1565b6001915050610586565b60ff8411156107c6576107c6610850565b50506001821b610586565b5060208310610133831016604e8410600b84101617156107f4575081810a610586565b6107fe838361072f565b806000190482111561081257610812610850565b029392505050565b600081600019048311821515161561083457610834610850565b500290565b60008282101561084b5761084b610850565b500390565b634e487b7160e01b600052601160045260246000fdfea2646970667358221220b66fc794fbca0536355abd67a782ac6a9194aaf7601c2523f308f0dd208ba4a664736f6c63430008070033
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
[ Download: CSV Export ]
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.