Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 2 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 19437183 | 701 days ago | Contract Creation | 0 ETH | |||
| 0x61012060 | 19437183 | 701 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
PriceFeed
Compiler Version
v0.8.17+commit.8df45f5f
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.17;
import "./Interfaces/IPriceFeed.sol";
import "./Interfaces/IFallbackCaller.sol";
import "./Dependencies/AggregatorV3Interface.sol";
import "./Dependencies/BaseMath.sol";
import "./Dependencies/EbtcMath.sol";
import "./Dependencies/AuthNoOwner.sol";
import "./FixedAdapter.sol";
/*
* PriceFeed for mainnet deployment, it connects to two Chainlink's live feeds, ETH:BTC and
* stETH:ETH, which are used to aggregate the price feed of stETH:BTC in conjuction.
* It also allows for a fallback oracle to intervene in case that the primary Chainlink oracle fails.
*
* The PriceFeed uses Chainlink as primary oracle and allows for an optional fallback source. It contains logic for
* switching oracles based on oracle failures, timeouts, and conditions for returning to the primary
* Chainlink oracle. In addition, it contains the mechanism to add or remove the fallback oracle through governance.
*/
contract PriceFeed is BaseMath, IPriceFeed, AuthNoOwner {
string public constant NAME = "PriceFeed";
// Chainlink oracles in mainnet
AggregatorV3Interface public immutable ETH_BTC_CL_FEED;
AggregatorV3Interface public immutable STETH_ETH_CL_FEED;
// STETH_ETH_FIXED_FEED must have the same decimals as STETH_ETH_CL_FEED
AggregatorV3Interface public immutable STETH_ETH_FIXED_FEED;
uint256 public immutable DENOMINATOR;
uint256 public immutable SCALED_DECIMAL;
// Fallback feed
IFallbackCaller public fallbackCaller; // Wrapper contract that calls the fallback system
// Maximum time period allowed since Chainlink's latest round data timestamp, beyond which Chainlink is considered frozen.
uint256 public constant TIMEOUT_ETH_BTC_FEED = 4800; // 1 hours & 20min: 60 * 80
uint256 public constant TIMEOUT_STETH_ETH_FEED = 90000; // 25 hours: 60 * 60 * 25
uint256 constant INVALID_PRICE = 0;
/**
* @notice Maximum number of resulting and feed decimals
*/
uint8 public constant MAX_DECIMALS = 18;
// Maximum deviation allowed between two consecutive Chainlink oracle prices. 18-digit precision.
uint256 public constant MAX_PRICE_DEVIATION_FROM_PREVIOUS_ROUND = 5e17; // 50%
/*
* The maximum relative price difference between two oracle responses allowed in order for the PriceFeed
* to return to using the Chainlink oracle. 18-digit precision.
*/
uint256 public constant MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES = 5e16; // 5%
// The last good price seen from an oracle by eBTC
uint256 public lastGoodPrice;
// The current status of the PriceFeed, which determines the conditions for the next price fetch attempt
Status public status;
// Dynamic feed = Chainlink stETH/ETH feed
// Static feed = 1:1 FixedAdapter
// defaults to static feed
bool public useDynamicFeed;
// --- Dependency setters ---
/// @notice Sets the addresses of the contracts and initializes the system
/// @param _fallbackCallerAddress The address of the Fallback oracle contract
/// @param _authorityAddress The address of the Authority contract
/// @param _collEthCLFeed The address of the collateral-ETH ChainLink feed
/// @param _ethBtcCLFeed The address of the ETH-BTC ChainLink feed
constructor(
address _fallbackCallerAddress,
address _authorityAddress,
address _collEthCLFeed,
address _ethBtcCLFeed,
bool _useDynamicFeed
) {
fallbackCaller = IFallbackCaller(_fallbackCallerAddress);
_initializeAuthority(_authorityAddress);
emit FallbackCallerChanged(address(0), _fallbackCallerAddress);
ETH_BTC_CL_FEED = AggregatorV3Interface(_ethBtcCLFeed);
STETH_ETH_CL_FEED = AggregatorV3Interface(_collEthCLFeed);
STETH_ETH_FIXED_FEED = new FixedAdapter();
uint8 ethBtcDecimals = ETH_BTC_CL_FEED.decimals();
require(ethBtcDecimals <= MAX_DECIMALS);
uint8 stEthEthDecimals = STETH_ETH_CL_FEED.decimals();
require(stEthEthDecimals <= MAX_DECIMALS);
require(stEthEthDecimals == STETH_ETH_FIXED_FEED.decimals());
DENOMINATOR =
10 ** ((stEthEthDecimals > ethBtcDecimals ? stEthEthDecimals : ethBtcDecimals) * 2);
SCALED_DECIMAL = stEthEthDecimals > ethBtcDecimals
? 10 ** (stEthEthDecimals - ethBtcDecimals)
: 10 ** (ethBtcDecimals - stEthEthDecimals);
useDynamicFeed = _useDynamicFeed;
// Get an initial price from Chainlink to serve as first reference for lastGoodPrice
ChainlinkResponse memory chainlinkResponse = _getCurrentChainlinkResponse();
ChainlinkResponse memory prevChainlinkResponse = _getPrevChainlinkResponse(
chainlinkResponse.roundEthBtcId,
chainlinkResponse.roundStEthEthId
);
require(
!_chainlinkIsBroken(chainlinkResponse, prevChainlinkResponse) &&
!_chainlinkIsFrozen(chainlinkResponse),
"PriceFeed: Chainlink must be working and current"
);
_storeChainlinkPrice(chainlinkResponse.answer);
// Explicitly set initial system status after `require` checks
status = Status.chainlinkWorking;
// emit STETH_ETH_FIXED_FEED address
emit CollateralFeedSourceUpdated(address(_collateralFeed()));
}
// --- Functions ---
function setCollateralFeedSource(bool _useDynamicFeed) external requiresAuth {
useDynamicFeed = _useDynamicFeed;
emit CollateralFeedSourceUpdated(address(_collateralFeed()));
}
/// @notice Returns the latest price obtained from the Oracle
/// @dev Called by eBTC functions that require a current price. Also callable permissionlessly.
/// @dev Non-view function - it updates and stores the last good price seen by eBTC.
/// @dev Uses a main oracle (Chainlink) and a fallback oracle in case Chainlink fails. If both fail, it uses the last good price seen by eBTC.
/// @dev The fallback oracle address can be swapped by the Authority. The fallback oracle must conform to the IFallbackCaller interface.
/// @return The latest price fetched from the Oracle
function fetchPrice() external override returns (uint256) {
// Get current and previous price data from Chainlink, and current price data from Fallback
ChainlinkResponse memory chainlinkResponse = _getCurrentChainlinkResponse();
ChainlinkResponse memory prevChainlinkResponse = _getPrevChainlinkResponse(
chainlinkResponse.roundEthBtcId,
chainlinkResponse.roundStEthEthId
);
FallbackResponse memory fallbackResponse = _getCurrentFallbackResponse();
// --- CASE 1: System fetched last price from Chainlink ---
if (status == Status.chainlinkWorking) {
// If Chainlink is broken, try Fallback
if (_chainlinkIsBroken(chainlinkResponse, prevChainlinkResponse)) {
// If Fallback is broken then both oracles are untrusted, so return the last good price
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.bothOraclesUntrusted);
return INVALID_PRICE;
}
/*
* If Fallback is only frozen but otherwise returning valid data, return the last good price.
* Fallback may need to be tipped to return current data.
*/
if (_fallbackIsFrozen(fallbackResponse)) {
_changeStatus(Status.usingFallbackChainlinkUntrusted);
return INVALID_PRICE;
}
// If Chainlink is broken and Fallback is working, switch to Fallback and return current Fallback price
_changeStatus(Status.usingFallbackChainlinkUntrusted);
return _storeFallbackPrice(fallbackResponse);
}
// If Chainlink is frozen, try Fallback
if (_chainlinkIsFrozen(chainlinkResponse)) {
// If Fallback is broken too, remember Fallback broke, and return last good price
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.usingChainlinkFallbackUntrusted);
return INVALID_PRICE;
}
// If Fallback is frozen or working, remember Chainlink froze, and switch to Fallback
_changeStatus(Status.usingFallbackChainlinkFrozen);
if (_fallbackIsFrozen(fallbackResponse)) {
return INVALID_PRICE;
}
// If Fallback is working, use it
return _storeFallbackPrice(fallbackResponse);
}
// If Chainlink price has changed by > 50% between two consecutive rounds, compare it to Fallback's price
if (_chainlinkPriceChangeAboveMax(chainlinkResponse, prevChainlinkResponse)) {
// If Fallback is broken, both oracles are untrusted, and return last good price
// We don't trust CL for now given this large price differential
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.bothOraclesUntrusted);
return INVALID_PRICE;
}
// If Fallback is frozen, switch to Fallback and return last good price
// We don't trust CL for now given this large price differential
if (_fallbackIsFrozen(fallbackResponse)) {
_changeStatus(Status.usingFallbackChainlinkUntrusted);
return INVALID_PRICE;
}
/*
* If Fallback is live and both oracles have a similar price, conclude that Chainlink's large price deviation between
* two consecutive rounds was likely a legitmate market price movement, and so continue using Chainlink
*/
if (_bothOraclesSimilarPrice(chainlinkResponse, fallbackResponse)) {
return _storeChainlinkPrice(chainlinkResponse.answer);
}
// If Fallback is live but the oracles differ too much in price, conclude that Chainlink's initial price deviation was
// an oracle failure. Switch to Fallback, and use Fallback price
_changeStatus(Status.usingFallbackChainlinkUntrusted);
return _storeFallbackPrice(fallbackResponse);
}
// If Chainlink is working and Fallback is broken, remember Fallback is broken
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.usingChainlinkFallbackUntrusted);
}
// If Chainlink is working, return Chainlink current price (no status change)
return _storeChainlinkPrice(chainlinkResponse.answer);
}
// --- CASE 2: The system fetched last price from Fallback ---
if (status == Status.usingFallbackChainlinkUntrusted) {
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.bothOraclesUntrusted);
return INVALID_PRICE;
}
/*
* If Fallback is only frozen but otherwise returning valid data, just return the last good price.
* Fallback may need to be tipped to return current data.
*/
if (_fallbackIsFrozen(fallbackResponse)) {
return INVALID_PRICE;
}
// If both Fallback and Chainlink are live, unbroken, and reporting similar prices, switch back to Chainlink
if (
_bothOraclesLiveAndUnbrokenAndSimilarPrice(
chainlinkResponse,
prevChainlinkResponse,
fallbackResponse
)
) {
_changeStatus(Status.chainlinkWorking);
return _storeChainlinkPrice(chainlinkResponse.answer);
}
// Otherwise, use Fallback price
return _storeFallbackPrice(fallbackResponse);
}
// --- CASE 3: Both oracles were untrusted at the last price fetch ---
if (status == Status.bothOraclesUntrusted) {
/*
* If there's no fallback, only use Chainlink
*/
if (address(fallbackCaller) == address(0)) {
// If CL has resumed working
if (
!_chainlinkIsBroken(chainlinkResponse, prevChainlinkResponse) &&
!_chainlinkIsFrozen(chainlinkResponse) &&
!_chainlinkPriceChangeAboveMax(chainlinkResponse, prevChainlinkResponse)
) {
_changeStatus(Status.usingChainlinkFallbackUntrusted);
return _storeChainlinkPrice(chainlinkResponse.answer);
} else {
return INVALID_PRICE;
}
}
/*
* If both oracles are now live, unbroken and similar price, we assume that they are reporting
* accurately, and so we switch back to Chainlink.
*/
if (
_bothOraclesLiveAndUnbrokenAndSimilarPrice(
chainlinkResponse,
prevChainlinkResponse,
fallbackResponse
)
) {
_changeStatus(Status.chainlinkWorking);
return _storeChainlinkPrice(chainlinkResponse.answer);
}
// Otherwise, return the last good price - both oracles are still untrusted (no status change)
return INVALID_PRICE;
}
// --- CASE 4: Using Fallback, and Chainlink is frozen ---
if (status == Status.usingFallbackChainlinkFrozen) {
if (_chainlinkIsBroken(chainlinkResponse, prevChainlinkResponse)) {
// If both Oracles are broken, return last good price
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.bothOraclesUntrusted);
return INVALID_PRICE;
}
// If Chainlink is broken, remember it and switch to using Fallback
_changeStatus(Status.usingFallbackChainlinkUntrusted);
if (_fallbackIsFrozen(fallbackResponse)) {
return INVALID_PRICE;
}
// If Fallback is working, return Fallback current price
return _storeFallbackPrice(fallbackResponse);
}
if (_chainlinkIsFrozen(chainlinkResponse)) {
// if Chainlink is frozen and Fallback is broken, remember Fallback broke, and return last good price
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.usingChainlinkFallbackUntrusted);
return INVALID_PRICE;
}
// If both are frozen, just use lastGoodPrice
if (_fallbackIsFrozen(fallbackResponse)) {
return INVALID_PRICE;
}
// if Chainlink is frozen and Fallback is working, keep using Fallback (no status change)
return _storeFallbackPrice(fallbackResponse);
}
if (_chainlinkPriceChangeAboveMax(chainlinkResponse, prevChainlinkResponse)) {
// if Chainlink price is deviated between rounds and fallback is broken, just use lastGoodPrice
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.bothOraclesUntrusted);
return INVALID_PRICE;
}
// If Chainlink price is deviated between rounds, remember it and keep using fallback
_changeStatus(Status.usingFallbackChainlinkUntrusted);
// If fallback is frozen, just use lastGoodPrice
if (_fallbackIsFrozen(fallbackResponse)) {
return INVALID_PRICE;
}
// otherwise fallback is working and keep using its latest response
return _storeFallbackPrice(fallbackResponse);
}
// if Chainlink is live and Fallback is broken, remember Fallback broke, and return Chainlink price
if (_fallbackIsBroken(fallbackResponse)) {
_changeStatus(Status.usingChainlinkFallbackUntrusted);
return _storeChainlinkPrice(chainlinkResponse.answer);
}
// If Chainlink is live and Fallback is frozen, just use last good price (no status change) since we have no basis for comparison
if (_fallbackIsFrozen(fallbackResponse)) {
return INVALID_PRICE;
}
// If Chainlink is live and Fallback is working, compare prices. Switch to Chainlink
// if prices are within 5%, and return Chainlink price.
if (_bothOraclesSimilarPrice(chainlinkResponse, fallbackResponse)) {
_changeStatus(Status.chainlinkWorking);
return _storeChainlinkPrice(chainlinkResponse.answer);
}
// Otherwise if Chainlink is live but price not within 5% of Fallback, distrust Chainlink, and return Fallback price
_changeStatus(Status.usingFallbackChainlinkUntrusted);
return _storeFallbackPrice(fallbackResponse);
}
// --- CASE 5: Using Chainlink, Fallback is untrusted ---
if (status == Status.usingChainlinkFallbackUntrusted) {
// If Chainlink breaks, now both oracles are untrusted
if (_chainlinkIsBroken(chainlinkResponse, prevChainlinkResponse)) {
_changeStatus(Status.bothOraclesUntrusted);
return INVALID_PRICE;
}
// If Chainlink is frozen, return last good price (no status change)
if (_chainlinkIsFrozen(chainlinkResponse)) {
return INVALID_PRICE;
}
// If Chainlink is live but deviated >50% from it's previous price and Fallback is still untrusted, switch
// to bothOraclesUntrusted and return last good price
if (_chainlinkPriceChangeAboveMax(chainlinkResponse, prevChainlinkResponse)) {
_changeStatus(Status.bothOraclesUntrusted);
return INVALID_PRICE;
}
// If Chainlink and Fallback are both live, unbroken and similar price, switch back to chainlinkWorking and return Chainlink price
if (
_bothOraclesLiveAndUnbrokenAndSimilarPrice(
chainlinkResponse,
prevChainlinkResponse,
fallbackResponse
)
) {
if (address(fallbackCaller) != address(0)) {
_changeStatus(Status.chainlinkWorking);
}
return _storeChainlinkPrice(chainlinkResponse.answer);
}
// Otherwise if Chainlink is live and deviated <50% from it's previous price and Fallback is still untrusted,
// return Chainlink price (no status change)
return _storeChainlinkPrice(chainlinkResponse.answer);
}
/// @audit This should never be used, but we added it for the Certora Prover
return INVALID_PRICE;
}
// --- Governance Functions ---
/// @notice Sets a new fallback oracle
/// @dev Healthy response of new oracle is checked, with extra event emitted on failure
/// @param _fallbackCaller The address of the new IFallbackCaller compliant oracle\
function setFallbackCaller(address _fallbackCaller) external requiresAuth {
// health check-up before officially set it up
IFallbackCaller newFallbackCaler = IFallbackCaller(_fallbackCaller);
FallbackResponse memory fallbackResponse;
if (_fallbackCaller != address(0)) {
try newFallbackCaler.getFallbackResponse() returns (
uint256 answer,
uint256 timestampRetrieved,
bool success
) {
fallbackResponse.answer = answer;
fallbackResponse.timestamp = timestampRetrieved;
fallbackResponse.success = success;
if (
!_fallbackIsBroken(fallbackResponse) &&
!_responseTimeout(fallbackResponse.timestamp, newFallbackCaler.fallbackTimeout())
) {
address oldFallbackCaller = address(fallbackCaller);
fallbackCaller = newFallbackCaler;
emit FallbackCallerChanged(oldFallbackCaller, _fallbackCaller);
}
} catch {
emit UnhealthyFallbackCaller(_fallbackCaller, block.timestamp);
}
} else {
address oldFallbackCaller = address(fallbackCaller);
// NOTE: assume intentionally bricking fallback!!!
fallbackCaller = newFallbackCaler;
emit FallbackCallerChanged(oldFallbackCaller, _fallbackCaller);
}
}
// --- Helper functions ---
/// @notice Checks if Chainlink oracle is broken by checking both the current and previous responses
/// @dev Chainlink is considered broken if its current or previous round data is in any way bad. We check the previous round for two reasons.
/// @dev 1. It is necessary data for the price deviation check in case 1
/// @dev 2. Chainlink is the PriceFeed's preferred primary oracle - having two consecutive valid round responses adds peace of mind when using or returning to Chainlink.
/// @param _currentResponse The latest response from the Chainlink oracle
/// @param _prevResponse The previous response from the Chainlink oracle
/// @return A boolean indicating whether the Chainlink oracle is broken
function _chainlinkIsBroken(
ChainlinkResponse memory _currentResponse,
ChainlinkResponse memory _prevResponse
) internal view returns (bool) {
return _badChainlinkResponse(_currentResponse) || _badChainlinkResponse(_prevResponse);
}
/// @notice Checks for a bad response from the Chainlink oracle
/// @dev A response is considered bad if the success value reports failure, or if the timestamp is invalid (0 or in the future)
/// @param _response The response from the Chainlink oracle to evaluate
/// @return A boolean indicating whether the Chainlink oracle response is bad
function _badChainlinkResponse(ChainlinkResponse memory _response) internal view returns (bool) {
// Check for response call reverted
if (!_response.success) {
return true;
}
// Check for an invalid timestamp that is 0, or in the future
if (
_response.timestampEthBtc == 0 ||
_response.timestampEthBtc > block.timestamp ||
_response.timestampStEthEth == 0 ||
_response.timestampStEthEth > block.timestamp
) {
return true;
}
return false;
}
/// @notice Checks if the Chainlink oracle is frozen
/// @dev The oracle is considered frozen if either of the feed timestamps are older than the threshold specified by the static timeout thresholds
/// @param _response The response from the Chainlink oracle to evaluate
/// @return A boolean indicating whether the Chainlink oracle is frozen
function _chainlinkIsFrozen(ChainlinkResponse memory _response) internal view returns (bool) {
return
_responseTimeout(_response.timestampEthBtc, TIMEOUT_ETH_BTC_FEED) ||
_responseTimeout(_response.timestampStEthEth, TIMEOUT_STETH_ETH_FEED);
}
/// @notice Checks if the price change between Chainlink oracle rounds is above the maximum threshold allowed
/// @param _currentResponse The latest response from the Chainlink oracle
/// @param _prevResponse The previous response from the Chainlink oracle
/// @return A boolean indicating whether the price change from Chainlink oracle is above the maximum threshold allowed
function _chainlinkPriceChangeAboveMax(
ChainlinkResponse memory _currentResponse,
ChainlinkResponse memory _prevResponse
) internal pure returns (bool) {
uint256 minPrice = EbtcMath._min(_currentResponse.answer, _prevResponse.answer);
uint256 maxPrice = EbtcMath._max(_currentResponse.answer, _prevResponse.answer);
/*
* Use the larger price as the denominator:
* - If price decreased, the percentage deviation is in relation to the the previous price.
* - If price increased, the percentage deviation is in relation to the current price.
*/
uint256 percentDeviation = maxPrice > 0
? ((maxPrice - minPrice) * EbtcMath.DECIMAL_PRECISION) / maxPrice
: 0;
// Return true if price has more than doubled, or more than halved.
return percentDeviation > MAX_PRICE_DEVIATION_FROM_PREVIOUS_ROUND;
}
function _fallbackIsBroken(FallbackResponse memory _response) internal view returns (bool) {
// Check for response call reverted
if (!_response.success) {
return true;
}
// Check for an invalid timeStamp that is 0, or in the future
if (_response.timestamp == 0 || _response.timestamp > block.timestamp) {
return true;
}
// Check for zero price (FallbackCaller must ensure that the price is not negative and return 0 if it is)
if (_response.answer == 0) {
return true;
}
return false;
}
/// @notice Checks if the fallback oracle is frozen by comparing the current timestamp with the timeout value.
/// @param _fallbackResponse Response from the fallback oracle to check
/// @return A boolean indicating whether the fallback oracle is frozen.
function _fallbackIsFrozen(
FallbackResponse memory _fallbackResponse
) internal view returns (bool) {
return
_fallbackResponse.timestamp > 0 &&
_responseTimeout(_fallbackResponse.timestamp, fallbackCaller.fallbackTimeout());
}
function _responseTimeout(uint256 _timestamp, uint256 _timeout) internal view returns (bool) {
return block.timestamp - _timestamp > _timeout;
}
/// @notice Checks if both the Chainlink and fallback oracles are live, unbroken, and reporting similar prices.
/// @param _chainlinkResponse The latest response from the Chainlink oracle.
/// @param _prevChainlinkResponse The previous response from the Chainlink oracle.
/// @param _fallbackResponse The latest response from the fallback oracle.
/// @return A boolean indicating whether both oracles are live, unbroken, and reporting similar prices.
function _bothOraclesLiveAndUnbrokenAndSimilarPrice(
ChainlinkResponse memory _chainlinkResponse,
ChainlinkResponse memory _prevChainlinkResponse,
FallbackResponse memory _fallbackResponse
) internal view returns (bool) {
// Return false if either oracle is broken or frozen
if (
(address(fallbackCaller) != address(0) &&
(_fallbackIsBroken(_fallbackResponse) || _fallbackIsFrozen(_fallbackResponse))) ||
_chainlinkIsBroken(_chainlinkResponse, _prevChainlinkResponse) ||
_chainlinkIsFrozen(_chainlinkResponse)
) {
return false;
}
return _bothOraclesSimilarPrice(_chainlinkResponse, _fallbackResponse);
}
/// @notice Checks if the prices reported by the Chainlink and fallback oracles are similar, within the maximum deviation specified by MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES.
/// @param _chainlinkResponse The response from the Chainlink oracle.
/// @param _fallbackResponse The response from the fallback oracle.
/// @return A boolean indicating whether the prices reported by both oracles are similar.
function _bothOraclesSimilarPrice(
ChainlinkResponse memory _chainlinkResponse,
FallbackResponse memory _fallbackResponse
) internal view returns (bool) {
if (address(fallbackCaller) == address(0)) {
return true;
}
// Get the relative price difference between the oracles. Use the lower price as the denominator, i.e. the reference for the calculation.
uint256 minPrice = EbtcMath._min(_fallbackResponse.answer, _chainlinkResponse.answer);
if (minPrice == 0) return false;
uint256 maxPrice = EbtcMath._max(_fallbackResponse.answer, _chainlinkResponse.answer);
uint256 percentPriceDifference = ((maxPrice - minPrice) * EbtcMath.DECIMAL_PRECISION) /
minPrice;
/*
* Return true if the relative price difference is <= MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES: if so, we assume both oracles are probably reporting
* the honest market price, as it is unlikely that both have been broken/hacked and are still in-sync.
*/
return percentPriceDifference <= MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES;
}
/// @notice Changes the status of the oracle state machine
/// @param _status The new status of the contract.
function _changeStatus(Status _status) internal {
status = _status;
emit PriceFeedStatusChanged(_status);
}
/// @notice Stores the latest valid price.
/// @param _currentPrice The price to be stored.
function _storePrice(uint256 _currentPrice) internal {
emit LastGoodPriceUpdated(_currentPrice);
}
/// @notice Stores the price reported by the fallback oracle.
/// @param _fallbackResponse The latest response from the fallback oracle.
/// @return The price reported by the fallback oracle.
function _storeFallbackPrice(
FallbackResponse memory _fallbackResponse
) internal returns (uint256) {
_storePrice(_fallbackResponse.answer);
return _fallbackResponse.answer;
}
/// @notice Stores the price reported by the Chainlink oracle.
/// @param _answer The latest price reported by the Chainlink oracle.
/// @return The price reported by the Chainlink oracle.
function _storeChainlinkPrice(uint256 _answer) internal returns (uint256) {
_storePrice(_answer);
return _answer;
}
// --- Oracle response wrapper functions ---
/// @notice Retrieves the latest response from the fallback oracle. If the fallback oracle address is set to the zero address, it returns a failing struct.
/// @return fallbackResponse The latest response from the fallback oracle.
function _getCurrentFallbackResponse()
internal
view
returns (FallbackResponse memory fallbackResponse)
{
if (address(fallbackCaller) != address(0)) {
try fallbackCaller.getFallbackResponse() returns (
uint256 answer,
uint256 timestampRetrieved,
bool success
) {
fallbackResponse.answer = answer;
fallbackResponse.timestamp = timestampRetrieved;
fallbackResponse.success = success;
} catch {
// If call to Fallback reverts, return a zero response with success = false
}
} // If unset we return a zero response with success = false
// Return is implicit
}
function _collateralFeed() private view returns (AggregatorV3Interface) {
return useDynamicFeed ? STETH_ETH_CL_FEED : STETH_ETH_FIXED_FEED;
}
/// @notice Fetches Chainlink responses for the current round of data for both ETH-BTC and stETH-ETH price feeds.
/// @return chainlinkResponse A struct containing data retrieved from the price feeds, including the round IDs, timestamps, aggregated price, and a success flag.
function _getCurrentChainlinkResponse()
internal
view
returns (ChainlinkResponse memory chainlinkResponse)
{
// Try to get latest prices data:
int256 ethBtcAnswer;
int256 stEthEthAnswer;
try ETH_BTC_CL_FEED.latestRoundData() returns (
uint80 roundId,
int256 answer,
uint256,
/* startedAt */
uint256 timestamp,
uint80 /* answeredInRound */
) {
ethBtcAnswer = answer;
chainlinkResponse.roundEthBtcId = roundId;
chainlinkResponse.timestampEthBtc = timestamp;
} catch {
// If call to Chainlink aggregator reverts, return a zero response with success = false
return chainlinkResponse;
}
try _collateralFeed().latestRoundData() returns (
uint80 roundId,
int256 answer,
uint256,
/* startedAt */
uint256 timestamp,
uint80 /* answeredInRound */
) {
stEthEthAnswer = answer;
chainlinkResponse.roundStEthEthId = roundId;
chainlinkResponse.timestampStEthEth = timestamp;
} catch {
// If call to Chainlink aggregator reverts, return a zero response with success = false
return chainlinkResponse;
}
if (
_checkHealthyCLResponse(chainlinkResponse.roundEthBtcId, ethBtcAnswer) &&
_checkHealthyCLResponse(chainlinkResponse.roundStEthEthId, stEthEthAnswer)
) {
chainlinkResponse.answer = _formatClAggregateAnswer(ethBtcAnswer, stEthEthAnswer);
} else {
return chainlinkResponse;
}
chainlinkResponse.success = true;
}
/// @notice Returns if the CL feed is healthy or not, based on: negative value and null round id. For price aggregation
/// @param _roundId The aggregator round of the target CL feed
/// @param _answer CL price price reported for target feeds
/// @return The boolean state indicating CL response health for aggregation
function _checkHealthyCLResponse(uint80 _roundId, int256 _answer) internal view returns (bool) {
if (_answer <= 0) return false;
if (_roundId == 0) return false;
return true;
}
/// @notice Fetches Chainlink responses for the previous round of data for both ETH-BTC and stETH-ETH price feeds.
/// @param _currentRoundEthBtcId The current round ID for the ETH-BTC price feed.
/// @param _currentRoundStEthEthId The current round ID for the stETH-ETH price feed.
/// @return prevChainlinkResponse A struct containing data retrieved from the price feeds, including the round IDs, timestamps, aggregated price, and a success flag.
function _getPrevChainlinkResponse(
uint80 _currentRoundEthBtcId,
uint80 _currentRoundStEthEthId
) internal view returns (ChainlinkResponse memory prevChainlinkResponse) {
// If first round, early return
// Handles revert from underflow in _currentRoundEthBtcId - 1
// and _currentRoundStEthEthId - 1
// Behavior should be indentical to following block if this revert was caught
if (_currentRoundEthBtcId == 0 || _currentRoundStEthEthId == 0) {
return prevChainlinkResponse;
}
// Try to get latest prices data from prev round:
int256 ethBtcAnswer;
int256 stEthEthAnswer;
try ETH_BTC_CL_FEED.getRoundData(_currentRoundEthBtcId - 1) returns (
uint80 roundId,
int256 answer,
uint256,
/* startedAt */
uint256 timestamp,
uint80 /* answeredInRound */
) {
ethBtcAnswer = answer;
prevChainlinkResponse.roundEthBtcId = roundId;
prevChainlinkResponse.timestampEthBtc = timestamp;
} catch {
// If call to Chainlink aggregator reverts, return a zero response with success = false
return prevChainlinkResponse;
}
try _collateralFeed().getRoundData(_currentRoundStEthEthId - 1) returns (
uint80 roundId,
int256 answer,
uint256,
/* startedAt */
uint256 timestamp,
uint80 /* answeredInRound */
) {
stEthEthAnswer = answer;
prevChainlinkResponse.roundStEthEthId = roundId;
prevChainlinkResponse.timestampStEthEth = timestamp;
} catch {
// If call to Chainlink aggregator reverts, return a zero response with success = false
return prevChainlinkResponse;
}
if (
_checkHealthyCLResponse(prevChainlinkResponse.roundEthBtcId, ethBtcAnswer) &&
_checkHealthyCLResponse(prevChainlinkResponse.roundStEthEthId, stEthEthAnswer)
) {
prevChainlinkResponse.answer = _formatClAggregateAnswer(ethBtcAnswer, stEthEthAnswer);
} else {
return prevChainlinkResponse;
}
prevChainlinkResponse.success = true;
}
// @notice Returns the price of stETH:BTC in 18 decimals denomination
// @param _ethBtcAnswer CL price retrieve from ETH:BTC feed
// @param _stEthEthAnswer CL price retrieve from stETH:BTC feed
// @return The aggregated calculated price for stETH:BTC
function _formatClAggregateAnswer(
int256 _ethBtcAnswer,
int256 _stEthEthAnswer
) internal view returns (uint256) {
return
(SCALED_DECIMAL *
uint256(_ethBtcAnswer) *
uint256(_stEthEthAnswer) *
EbtcMath.DECIMAL_PRECISION) / DENOMINATOR;
}
}// SPDX-License-Identifier: MIT
// Code from https://github.com/smartcontractkit/chainlink/blob/master/evm-contracts/src/v0.6/interfaces/AggregatorV3Interface.sol
pragma solidity 0.8.17;
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: AGPL-3.0-only
pragma solidity 0.8.17;
import {Authority} from "./Authority.sol";
/// @notice Provides a flexible and updatable auth pattern which is completely separate from application logic.
/// @author Modified by BadgerDAO to remove owner
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
contract AuthNoOwner {
event AuthorityUpdated(address indexed user, Authority indexed newAuthority);
Authority private _authority;
bool private _authorityInitialized;
modifier requiresAuth() virtual {
require(isAuthorized(msg.sender, msg.sig), "Auth: UNAUTHORIZED");
_;
}
function authority() public view returns (Authority) {
return _authority;
}
function authorityInitialized() public view returns (bool) {
return _authorityInitialized;
}
function isAuthorized(address user, bytes4 functionSig) internal view virtual returns (bool) {
Authority auth = _authority; // Memoizing authority saves us a warm SLOAD, around 100 gas.
// Checking if the caller is the owner only after calling the authority saves gas in most cases, but be
// aware that this makes protected functions uncallable even to the owner if the authority is out of order.
return (address(auth) != address(0) && auth.canCall(user, address(this), functionSig));
}
/// @notice Changed constructor to initialize to allow flexiblity of constructor vs initializer use
/// @notice sets authorityInitiailzed flag to ensure only one use of
function _initializeAuthority(address newAuthority) internal {
require(address(_authority) == address(0), "Auth: authority is non-zero");
require(!_authorityInitialized, "Auth: authority already initialized");
_authority = Authority(newAuthority);
_authorityInitialized = true;
emit AuthorityUpdated(address(this), Authority(newAuthority));
}
}// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity 0.8.17;
/// @notice A generic interface for a contract which provides authorization data to an Auth instance.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Auth.sol)
/// @author Modified from Dappsys (https://github.com/dapphub/ds-auth/blob/master/src/auth.sol)
interface Authority {
function canCall(address user, address target, bytes4 functionSig) external view returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
contract BaseMath {
uint256 public constant DECIMAL_PRECISION = 1e18;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
library EbtcMath {
uint256 internal constant DECIMAL_PRECISION = 1e18;
uint256 public constant MAX_TCR = type(uint256).max;
/* Precision for Nominal ICR (independent of price). Rationale for the value:
*
* - Making it “too high” could lead to overflows.
* - Making it “too low” could lead to an ICR equal to zero, due to truncation from Solidity floor division.
*
* This value of 1e20 is chosen for safety: the NICR will only overflow for numerator > ~1e39 ETH,
* and will only truncate to 0 if the denominator is at least 1e20 times greater than the numerator.
*
*/
uint256 internal constant NICR_PRECISION = 1e20;
function _min(uint256 _a, uint256 _b) internal pure returns (uint256) {
return (_a < _b) ? _a : _b;
}
function _max(uint256 _a, uint256 _b) internal pure returns (uint256) {
return (_a >= _b) ? _a : _b;
}
/**
* credit to OpenZeppelin
* @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, "EbtcMath: downcast to uint128 will overflow");
return uint128(value);
}
/*
* Multiply two decimal numbers and use normal rounding rules:
* -round product up if 19'th mantissa digit >= 5
* -round product down if 19'th mantissa digit < 5
*
* Used only inside the exponentiation, _decPow().
*/
function decMul(uint256 x, uint256 y) internal pure returns (uint256 decProd) {
uint256 prod_xy = x * y;
decProd = (prod_xy + (DECIMAL_PRECISION / 2)) / DECIMAL_PRECISION;
}
/*
* _decPow: Exponentiation function for 18-digit decimal base, and integer exponent n.
*
* Uses the efficient "exponentiation by squaring" algorithm. O(log(n)) complexity.
*
* Called by two functions that represent time in units of minutes:
* 1) CdpManager._calcDecayedBaseRate
* 2) CommunityIssuance._getCumulativeIssuanceFraction
*
* The exponent is capped to avoid reverting due to overflow. The cap 525600000 equals
* "minutes in 1000 years": 60 * 24 * 365 * 1000
*
* If a period of > 1000 years is ever used as an exponent in either of the above functions, the result will be
* negligibly different from just passing the cap, since:
*
* In function 1), the decayed base rate will be 0 for 1000 years or > 1000 years
* In function 2), the difference in tokens issued at 1000 years and any time > 1000 years, will be negligible
*/
function _decPow(uint256 _base, uint256 _minutes) internal pure returns (uint256) {
if (_minutes > 525600000) {
_minutes = 525600000;
} // cap to avoid overflow
if (_minutes == 0) {
return DECIMAL_PRECISION;
}
uint256 y = DECIMAL_PRECISION;
uint256 x = _base;
uint256 n = _minutes;
// Exponentiation-by-squaring
while (n > 1) {
if (n % 2 == 0) {
x = decMul(x, x);
n = n / 2;
} else {
// if (n % 2 != 0)
y = decMul(x, y);
x = decMul(x, x);
n = (n - 1) / 2;
}
}
return decMul(x, y);
}
function _getAbsoluteDifference(uint256 _a, uint256 _b) internal pure returns (uint256) {
return (_a >= _b) ? (_a - _b) : (_b - _a);
}
function _computeNominalCR(uint256 _collShares, uint256 _debt) internal pure returns (uint256) {
if (_debt > 0) {
return (_collShares * NICR_PRECISION) / _debt;
}
// Return the maximal value for uint256 if the Cdp has a debt of 0. Represents "infinite" CR.
else {
// if (_debt == 0)
return MAX_TCR;
}
}
/// @dev Compute collateralization ratio, given stETH balance, price, and debt balance
function _computeCR(
uint256 _stEthBalance,
uint256 _debt,
uint256 _price
) internal pure returns (uint256) {
if (_debt > 0) {
uint256 newCollRatio = (_stEthBalance * _price) / _debt;
return newCollRatio;
}
// Return the maximal value for uint256 if the Cdp has a debt of 0. Represents "infinite" CR.
else {
// if (_debt == 0)
return MAX_TCR;
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
import {AggregatorV3Interface} from "./Dependencies/AggregatorV3Interface.sol";
contract FixedAdapter is AggregatorV3Interface {
uint8 public constant override decimals = 18;
uint256 public constant override version = 1;
/// @notice PriceFeed always fetches current and previous rounds. It's ok to
/// hardcode round IDs as long as they are greater than 0.
uint80 public constant CURRENT_ROUND = 2;
uint80 public constant PREVIOUS_ROUND = 1;
int256 internal constant ADAPTER_PRECISION = int256(10 ** decimals);
function description() external view returns (string memory) {
return "stETH/ETH Fixed Adapter";
}
// 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
)
{
require(_roundId == CURRENT_ROUND || _roundId == PREVIOUS_ROUND);
roundId = _roundId;
updatedAt = _roundId == CURRENT_ROUND ? block.timestamp : block.timestamp - 1;
answer = ADAPTER_PRECISION;
}
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
roundId = CURRENT_ROUND;
updatedAt = block.timestamp;
answer = ADAPTER_PRECISION;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IFallbackCaller {
// --- Events ---
event FallbackTimeOutChanged(uint256 _oldTimeOut, uint256 _newTimeOut);
// --- Function External View ---
// NOTE: The fallback oracle must always return its answer scaled to 18 decimals where applicable
// The system will assume an 18 decimal response for efficiency.
function getFallbackResponse() external view returns (uint256, uint256, bool);
// NOTE: this returns the timeout window interval for the fallback oracle instead
// of storing in the `PriceFeed` contract is retrieve for the `FallbackCaller`
function fallbackTimeout() external view returns (uint256);
// --- Function External Setter ---
function setFallbackTimeout(uint256 newFallbackTimeout) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IPriceFeed {
// --- Events ---
event LastGoodPriceUpdated(uint256 _lastGoodPrice);
event PriceFeedStatusChanged(Status newStatus);
event FallbackCallerChanged(
address indexed _oldFallbackCaller,
address indexed _newFallbackCaller
);
event UnhealthyFallbackCaller(address indexed _fallbackCaller, uint256 timestamp);
event CollateralFeedSourceUpdated(address indexed stEthFeed);
// --- Structs ---
struct ChainlinkResponse {
uint80 roundEthBtcId;
uint80 roundStEthEthId;
uint256 answer;
uint256 timestampEthBtc;
uint256 timestampStEthEth;
bool success;
}
struct FallbackResponse {
uint256 answer;
uint256 timestamp;
bool success;
}
// --- Enum ---
enum Status {
chainlinkWorking,
usingFallbackChainlinkUntrusted,
bothOraclesUntrusted,
usingFallbackChainlinkFrozen,
usingChainlinkFallbackUntrusted
}
// --- Function ---
function fetchPrice() external 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":"_fallbackCallerAddress","type":"address"},{"internalType":"address","name":"_authorityAddress","type":"address"},{"internalType":"address","name":"_collEthCLFeed","type":"address"},{"internalType":"address","name":"_ethBtcCLFeed","type":"address"},{"internalType":"bool","name":"_useDynamicFeed","type":"bool"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract Authority","name":"newAuthority","type":"address"}],"name":"AuthorityUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"stEthFeed","type":"address"}],"name":"CollateralFeedSourceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_oldFallbackCaller","type":"address"},{"indexed":true,"internalType":"address","name":"_newFallbackCaller","type":"address"}],"name":"FallbackCallerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_lastGoodPrice","type":"uint256"}],"name":"LastGoodPriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IPriceFeed.Status","name":"newStatus","type":"uint8"}],"name":"PriceFeedStatusChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_fallbackCaller","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"UnhealthyFallbackCaller","type":"event"},{"inputs":[],"name":"DECIMAL_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_BTC_CL_FEED","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_DECIMALS","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PRICE_DEVIATION_FROM_PREVIOUS_ROUND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PRICE_DIFFERENCE_BETWEEN_ORACLES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NAME","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALED_DECIMAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_ETH_CL_FEED","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STETH_ETH_FIXED_FEED","outputs":[{"internalType":"contract AggregatorV3Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMEOUT_ETH_BTC_FEED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIMEOUT_STETH_ETH_FEED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract Authority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"authorityInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fallbackCaller","outputs":[{"internalType":"contract IFallbackCaller","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fetchPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastGoodPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_useDynamicFeed","type":"bool"}],"name":"setCollateralFeedSource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fallbackCaller","type":"address"}],"name":"setFallbackCaller","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"status","outputs":[{"internalType":"enum IPriceFeed.Status","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"useDynamicFeed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
6101206040523480156200001257600080fd5b506040516200286c3803806200286c833981016040819052620000359162000aa9565b600180546001600160a01b0319166001600160a01b0387161790556200005b8462000413565b6040516001600160a01b038616906000907f633b20eaebf02bd523c44b01ff791580199b6217bae352f4cbdc95e1226fb550908290a36001600160a01b03808316608052831660a052604051620000b29062000a7e565b604051809103906000f080158015620000cf573d6000803e3d6000fd5b506001600160a01b031660c0816001600160a01b03168152505060006080516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200012c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000152919062000b21565b9050601260ff821611156200016657600080fd5b600060a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001cf919062000b21565b9050601260ff82161115620001e357600080fd5b60c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000224573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200024a919062000b21565b60ff168160ff16146200025c57600080fd5b8160ff168160ff161162000271578162000273565b805b6200028090600262000b5c565b6200028d90600a62000c7f565b60e05260ff80831690821611620002bd57620002aa818362000c90565b620002b790600a62000c7f565b620002d6565b620002c9828262000c90565b620002d690600a62000c7f565b6101009081526003805461ff0019168515159092029190911790556000620002fd62000527565b905060006200031b82600001518360200151620006bf60201b60201c565b9050620003298282620008cd565b1580156200033f57506200033d82620008f3565b155b620003aa5760405162461bcd60e51b815260206004820152603060248201527f5072696365466565643a20436861696e6c696e6b206d75737420626520776f7260448201526f1ada5b99c8185b990818dd5c9c995b9d60821b60648201526084015b60405180910390fd5b6040820151620003ba9062000928565b506003805460ff19169055620003cf62000939565b6001600160a01b03167f0bf6cc51307ce9e3a6e5ff2f9281a57123273aff808032156de6990798c4eb9460405160405180910390a250505050505050505062000d8f565b6000546001600160a01b0316156200046e5760405162461bcd60e51b815260206004820152601b60248201527f417574683a20617574686f72697479206973206e6f6e2d7a65726f00000000006044820152606401620003a1565b600054600160a01b900460ff1615620004d65760405162461bcd60e51b815260206004820152602360248201527f417574683a20617574686f7269747920616c726561647920696e697469616c696044820152621e995960ea1b6064820152608401620003a1565b600080546001600160a81b0319166001600160a01b038316908117600160a01b178255604051909130917fa3396fd7f6e0a21b50e5089d2da70d5ac0a3bbbd1f617a93f134b763899801989190a350565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526000806080516001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015620005bb575060408051601f3d908101601f19168201909252620005b89181019062000cc4565b60015b620005c557505090565b506001600160501b0390931686525060608501919091529150620005e862000939565b6001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa92505050801562000644575060408051601f3d908101601f19168201909252620006419181019062000cc4565b60015b6200064e57505090565b506001600160501b039093166020870152506080850191909152905082516200067890836200095a565b801562000691575060208301516200069190826200095a565b15620006ae57620006a3828262000991565b6040840152620006b3565b505090565b5050600160a082015290565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091526001600160501b03831615806200070f57506001600160501b038216155b620008c7576000806080516001600160a01b0316639a6fc8f560018762000737919062000d19565b6040516001600160e01b031960e084901b1681526001600160501b03909116600482015260240160a060405180830381865afa9250505080156200079a575060408051601f3d908101601f19168201909252620007979181019062000cc4565b60015b620007a7575050620008c7565b506001600160501b0390931686525060608501919091529150620007ca62000939565b6001600160a01b0316639a6fc8f5620007e560018762000d19565b6040516001600160e01b031960e084901b1681526001600160501b03909116600482015260240160a060405180830381865afa92505050801562000848575060408051601f3d908101601f19168201909252620008459181019062000cc4565b60015b62000855575050620008c7565b506001600160501b039093166020870152506080850191909152905082516200087f90836200095a565b801562000898575060208301516200089890826200095a565b15620008b557620008aa828262000991565b6040840152620008bd565b5050620008c7565b5050600160a08201525b92915050565b6000620008da83620009d5565b80620008ec5750620008ec82620009d5565b9392505050565b60006200090d82606001516112c062000a3160201b60201c565b80620008c757506080820151620008c79062015f9062000a31565b6000620009358262000a48565b5090565b600354600090610100900460ff1662000953575060c05190565b5060a05190565b60008082136200096d57506000620008c7565b826001600160501b03166000036200098857506000620008c7565b50600192915050565b600060e051670de0b6b3a7640000838561010051620009b1919062000d3c565b620009bd919062000d3c565b620009c9919062000d3c565b620008ec919062000d56565b60008160a00151620009e957506001919050565b60608201511580620009fe5750428260600151115b8062000a0c57506080820151155b8062000a1b5750428260800151115b1562000a2957506001919050565b506000919050565b60008162000a40844262000d79565b119392505050565b6040518181527f4d29de21de555af78a62fc82dd4bc05e9ae5b0660a37f04729527e0f22780cd39060200160405180910390a150565b6103ee806200247e83390190565b80516001600160a01b038116811462000aa457600080fd5b919050565b600080600080600060a0868803121562000ac257600080fd5b62000acd8662000a8c565b945062000add6020870162000a8c565b935062000aed6040870162000a8c565b925062000afd6060870162000a8c565b91506080860151801515811462000b1357600080fd5b809150509295509295909350565b60006020828403121562000b3457600080fd5b815160ff81168114620008ec57600080fd5b634e487b7160e01b600052601160045260246000fd5b60ff818116838216029081169081811462000b7b5762000b7b62000b46565b5092915050565b600181815b8085111562000bc357816000190482111562000ba75762000ba762000b46565b8085161562000bb557918102915b93841c939080029062000b87565b509250929050565b60008262000bdc57506001620008c7565b8162000beb57506000620008c7565b816001811462000c04576002811462000c0f5762000c2f565b6001915050620008c7565b60ff84111562000c235762000c2362000b46565b50506001821b620008c7565b5060208310610133831016604e8410600b841016171562000c54575081810a620008c7565b62000c60838362000b82565b806000190482111562000c775762000c7762000b46565b029392505050565b6000620008ec60ff84168362000bcb565b60ff8281168282160390811115620008c757620008c762000b46565b80516001600160501b038116811462000aa457600080fd5b600080600080600060a0868803121562000cdd57600080fd5b62000ce88662000cac565b945060208601519350604086015192506060860151915062000d0d6080870162000cac565b90509295509295909350565b6001600160501b0382811682821603908082111562000b7b5762000b7b62000b46565b8082028115828204841417620008c757620008c762000b46565b60008262000d7457634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115620008c757620008c762000b46565b60805160a05160c05160e0516101005161168062000dfe6000396000818161026001526112d20152600081816102b201526112a301526000818161019901526112100152600081816101d801526112350152600081816101ff01528181610a630152610c0401526116806000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806356e0c35e116100b857806397bc1e1b1161007c57806397bc1e1b146102d45780639a60bfe3146102e6578063a20baee6146102fb578063a3f4df7e1461030a578063b6f0e8ce1461033f578063bf7e214f1461035257600080fd5b806356e0c35e1461025b57806358a6aa88146102825780637a2fe2a9146102915780638151d751146102a4578063918f8674146102ad57600080fd5b80632388efb0116100ff5780632388efb0146101d35780632c9479f0146101fa57806345079cb414610221578063473baff11461022f5780634ce3e31f1461025157600080fd5b80630417cf8e1461013c5780630490be831461015b5780630fdb11cf14610172578063200d2ed21461017a5780632354d60014610194575b600080fd5b610144601281565b60405160ff90911681526020015b60405180910390f35b61016460025481565b604051908152602001610152565b610164610363565b6003546101879060ff1681565b6040516101529190611419565b6101bb7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610152565b6101bb7f000000000000000000000000000000000000000000000000000000000000000081565b6101bb7f000000000000000000000000000000000000000000000000000000000000000081565b61016466b1a2bc2ec5000081565b60035461024190610100900460ff1681565b6040519015158152602001610152565b61016462015f9081565b6101647f000000000000000000000000000000000000000000000000000000000000000081565b6101646706f05b59d3b2000081565b6001546101bb906001600160a01b031681565b6101646112c081565b6101647f000000000000000000000000000000000000000000000000000000000000000081565b600054600160a01b900460ff16610241565b6102f96102f4366004611452565b610733565b005b610164670de0b6b3a764000081565b61033260405180604001604052806009815260200168141c9a58d95199595960ba1b81525081565b604051610152919061146f565b6102f961034d3660046114bd565b6107e2565b6000546001600160a01b03166101bb565b60008061036e610a56565b9050600061038482600001518360200151610bce565b90506000610390610db1565b9050600060035460ff1660048111156103ab576103ab611403565b036104dc576103ba8383610e6f565b15610414576103c881610e90565b156103e1576103d76002610edd565b6000935050505090565b6103ea81610f3b565b156103f9576103d76001610edd565b6104036001610edd565b61040c81610f9a565b935050505090565b61041d83610fae565b1561045c5761042b81610e90565b1561043a576103d76004610edd565b6104446003610edd565b61044d81610f3b565b15610403576000935050505090565b6104668383610fd7565b156104b75761047481610e90565b15610483576103d76002610edd565b61048c81610f3b565b1561049b576103d76001610edd565b6104a58382611050565b156103f95761040c83604001516110e7565b6104c081610e90565b156104cf576104cf6004610edd565b61040c83604001516110e7565b600160035460ff1660048111156104f5576104f5611403565b036105445761050381610e90565b15610512576103d76002610edd565b61051b81610f3b565b1561052a576000935050505090565b6105358383836110f6565b15610403576104cf6000610edd565b600260035460ff16600481111561055d5761055d611403565b036105cb576001546001600160a01b03166105b15761057c8383610e6f565b15801561058f575061058d83610fae565b155b80156105a257506105a08383610fd7565b155b156103d7576104cf6004610edd565b6105bc8383836110f6565b156103d7576104cf6000610edd565b6003805460ff1660048111156105e3576105e3611403565b036106a0576105f28383610e6f565b156106195761060081610e90565b1561060f576103d76002610edd565b6104446001610edd565b61062283610fae565b1561063f5761063081610e90565b15610444576103d76004610edd565b6106498383610fd7565b156106575761060081610e90565b61066081610e90565b1561066f576104cf6004610edd565b61067881610f3b565b15610687576000935050505090565b6106918382611050565b156103f9576104cf6000610edd565b600460035460ff1660048111156106b9576106b9611403565b036103d7576106c88383610e6f565b156106d7576103d76002610edd565b6106e083610fae565b156106ef576000935050505090565b6106f98383610fd7565b15610708576103d76002610edd565b6107138383836110f6565b156104cf576001546001600160a01b0316156104cf576104cf6000610edd565b610749336000356001600160e01b031916611164565b61078f5760405162461bcd60e51b8152602060048201526012602482015271105d5d1a0e8815539055551213d49256915160721b60448201526064015b60405180910390fd5b6003805461ff001916610100831515021790556107aa6111fb565b6001600160a01b03167f0bf6cc51307ce9e3a6e5ff2f9281a57123273aff808032156de6990798c4eb9460405160405180910390a250565b6107f8336000356001600160e01b031916611164565b6108395760405162461bcd60e51b8152602060048201526012602482015271105d5d1a0e8815539055551213d49256915160721b6044820152606401610786565b604080516060810182526000808252602082018190529181019190915281906001600160a01b03831615610a0057816001600160a01b031663bbcb625f6040518163ffffffff1660e01b8152600401606060405180830381865afa9250505080156108c1575060408051601f3d908101601f191682019092526108be918101906114e6565b60015b61090d57826001600160a01b03167f8c32448b27b941b35da4a33f2afee2fdada7d1149551d0d4c28e7feeff3663064260405161090091815260200190565b60405180910390a2505050565b82845260208401829052801515604085015261092884610e90565b1580156109a1575061099f8460200151866001600160a01b0316634277bc066040518163ffffffff1660e01b8152600401602060405180830381865afa158015610976573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099a919061151f565b611257565b155b156109f857600180546001600160a01b038781166001600160a01b03198316179092556040519082169188169082907f633b20eaebf02bd523c44b01ff791580199b6217bae352f4cbdc95e1226fb55090600090a3505b505050505050565b600180546001600160a01b038481166001600160a01b03198316179092556040519082169185169082907f633b20eaebf02bd523c44b01ff791580199b6217bae352f4cbdc95e1226fb55090600090a350505050565b610a5e6113b9565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015610adb575060408051601f3d908101601f19168201909252610ad891810190611554565b60015b610ae457505090565b506001600160501b0390931686525060608501919091529150610b056111fb565b6001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015610b5e575060408051601f3d908101601f19168201909252610b5b91810190611554565b60015b610b6757505090565b506001600160501b03909316602087015250608085019190915290508251610b8f908361126c565b8015610ba45750610ba483602001518261126c565b15610bbd57610bb3828261129f565b6040840152610bc2565b505090565b5050600160a082015290565b610bd66113b9565b6001600160501b0383161580610bf357506001600160501b038216155b610dab576000806001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016639a6fc8f5610c346001886115ba565b6040516001600160e01b031960e084901b1681526001600160501b03909116600482015260240160a060405180830381865afa925050508015610c94575060408051601f3d908101601f19168201909252610c9191810190611554565b60015b610c9f575050610dab565b506001600160501b0390931686525060608501919091529150610cc06111fb565b6001600160a01b0316639a6fc8f5610cd96001876115ba565b6040516001600160e01b031960e084901b1681526001600160501b03909116600482015260240160a060405180830381865afa925050508015610d39575060408051601f3d908101601f19168201909252610d3691810190611554565b60015b610d44575050610dab565b506001600160501b03909316602087015250608085019190915290508251610d6c908361126c565b8015610d815750610d8183602001518261126c565b15610d9a57610d90828261129f565b6040840152610da1565b5050610dab565b5050600160a08201525b92915050565b610dd7604051806060016040528060008152602001600081526020016000151581525090565b6001546001600160a01b031615610e6c57600160009054906101000a90046001600160a01b03166001600160a01b031663bbcb625f6040518163ffffffff1660e01b8152600401606060405180830381865afa925050508015610e57575060408051601f3d908101601f19168201909252610e54918101906114e6565b60015b15610e6c579183526020830152151560408201525b90565b6000610e7a83611314565b80610e895750610e8982611314565b9392505050565b60008160400151610ea357506001919050565b60208201511580610eb75750428260200151115b15610ec457506001919050565b8151600003610ed557506001919050565b506000919050565b6003805482919060ff19166001836004811115610efc57610efc611403565b02179055507f5c57579a8214fe4f710c1c56fa829f045b9fa6d225a744225a30c32188064d4e81604051610f309190611419565b60405180910390a150565b6000808260200151118015610dab57506020808301516001546040805163213bde0360e11b81529051610dab946001600160a01b0390931692634277bc0692600480820193918290030181865afa158015610976573d6000803e3d6000fd5b6000610fa98260000151611363565b505190565b6000610fc082606001516112c0611257565b80610dab5750610dab826080015162015f90611257565b600080610fec84604001518460400151611393565b90506000611002856040015185604001516113a9565b9050600080821161101457600061103c565b81670de0b6b3a764000061102885836115e1565b61103291906115f4565b61103c919061160b565b6706f05b59d3b20000109695505050505050565b6001546000906001600160a01b031661106b57506001610dab565b600061107f83600001518560400151611393565b905080600003611093576000915050610dab565b60006110a7846000015186604001516113a9565b9050600082670de0b6b3a76400006110bf82856115e1565b6110c991906115f4565b6110d3919061160b565b66b1a2bc2ec5000010159695505050505050565b60006110f282611363565b5090565b6001546000906001600160a01b031615801590611126575061111782610e90565b80611126575061112682610f3b565b8061113657506111368484610e6f565b80611145575061114584610fae565b1561115257506000610e89565b61115c8483611050565b949350505050565b600080546001600160a01b0316801580159061115c575060405163b700961360e01b81526001600160a01b0385811660048301523060248301526001600160e01b03198516604483015282169063b700961390606401602060405180830381865afa1580156111d7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115c919061162d565b600354600090610100900460ff1661123257507f000000000000000000000000000000000000000000000000000000000000000090565b507f000000000000000000000000000000000000000000000000000000000000000090565b60008161126484426115e1565b119392505050565b600080821361127d57506000610dab565b826001600160501b031660000361129657506000610dab565b50600192915050565b60007f0000000000000000000000000000000000000000000000000000000000000000670de0b6b3a7640000836112f6867f00000000000000000000000000000000000000000000000000000000000000006115f4565b61130091906115f4565b61130a91906115f4565b610e89919061160b565b60008160a0015161132757506001919050565b6060820151158061133b5750428260600151115b8061134857506080820151155b806113565750428260800151115b15610ed557506001919050565b6040518181527f4d29de21de555af78a62fc82dd4bc05e9ae5b0660a37f04729527e0f22780cd390602001610f30565b60008183106113a25781610e89565b5090919050565b6000818310156113a25781610e89565b6040518060c0016040528060006001600160501b0316815260200160006001600160501b031681526020016000815260200160008152602001600081526020016000151581525090565b634e487b7160e01b600052602160045260246000fd5b602081016005831061143b57634e487b7160e01b600052602160045260246000fd5b91905290565b801515811461144f57600080fd5b50565b60006020828403121561146457600080fd5b8135610e8981611441565b600060208083528351808285015260005b8181101561149c57858101830151858201604001528201611480565b506000604082860101526040601f19601f8301168501019250505092915050565b6000602082840312156114cf57600080fd5b81356001600160a01b0381168114610e8957600080fd5b6000806000606084860312156114fb57600080fd5b8351925060208401519150604084015161151481611441565b809150509250925092565b60006020828403121561153157600080fd5b5051919050565b80516001600160501b038116811461154f57600080fd5b919050565b600080600080600060a0868803121561156c57600080fd5b61157586611538565b945060208601519350604086015192506060860151915061159860808701611538565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b6001600160501b038281168282160390808211156115da576115da6115a4565b5092915050565b81810381811115610dab57610dab6115a4565b8082028115828204841417610dab57610dab6115a4565b60008261162857634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561163f57600080fd5b8151610e898161144156fea2646970667358221220128fcd3f494b5397341e7c92e1bcfcfaac459065cfaae5daa44c5b82a92b6b3b64736f6c63430008110033608060405234801561001057600080fd5b506103ce806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80637284e4161161005b5780637284e416146100d75780639a6fc8f514610116578063d5c8610c1461015d578063feaf968c1461016557600080fd5b8063313ce5671461008257806354fd4d50146100a15780635a901295146100b7575b600080fd5b61008a601281565b60405160ff90911681526020015b60405180910390f35b6100a9600181565b604051908152602001610098565b6100bf600181565b6040516001600160501b039091168152602001610098565b604080518082018252601781527f73744554482f45544820466978656420416461707465720000000000000000006020820152905161009891906101f8565b610129610124366004610246565b61016d565b604080516001600160501b03968716815260208101959095528401929092526060830152909116608082015260a001610098565b6100bf600281565b6101296101dc565b6000808080806001600160501b0386166002148061019457506001600160501b0386166001145b61019d57600080fd5b8594506001600160501b0385166002146101c1576101bc60014261028c565b6101c3565b425b91506101d16012600a610389565b935091939590929450565b600260008042816101ef6012600a610389565b93509091929394565b600060208083528351808285015260005b8181101561022557858101830151858201604001528201610209565b506000604082860101526040601f19601f8301168501019250505092915050565b60006020828403121561025857600080fd5b81356001600160501b038116811461026f57600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561029f5761029f610276565b92915050565b600181815b808511156102e05781600019048211156102c6576102c6610276565b808516156102d357918102915b93841c93908002906102aa565b509250929050565b6000826102f75750600161029f565b816103045750600061029f565b816001811461031a576002811461032457610340565b600191505061029f565b60ff84111561033557610335610276565b50506001821b61029f565b5060208310610133831016604e8410600b8410161715610363575081810a61029f565b61036d83836102a5565b806000190482111561038157610381610276565b029392505050565b600061026f60ff8416836102e856fea2646970667358221220582e2bdc4501c188f91e6fb6d50e70e501cb793402ccf5aa8414f1a92a8cfc3664736f6c6343000811003300000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a095d44831c26cfb6acb806a6531ae3ca32dbc100000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c52812000000000000000000000000e61ebc2b9fd43bca89e38c707acb280907f447cb0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101375760003560e01c806356e0c35e116100b857806397bc1e1b1161007c57806397bc1e1b146102d45780639a60bfe3146102e6578063a20baee6146102fb578063a3f4df7e1461030a578063b6f0e8ce1461033f578063bf7e214f1461035257600080fd5b806356e0c35e1461025b57806358a6aa88146102825780637a2fe2a9146102915780638151d751146102a4578063918f8674146102ad57600080fd5b80632388efb0116100ff5780632388efb0146101d35780632c9479f0146101fa57806345079cb414610221578063473baff11461022f5780634ce3e31f1461025157600080fd5b80630417cf8e1461013c5780630490be831461015b5780630fdb11cf14610172578063200d2ed21461017a5780632354d60014610194575b600080fd5b610144601281565b60405160ff90911681526020015b60405180910390f35b61016460025481565b604051908152602001610152565b610164610363565b6003546101879060ff1681565b6040516101529190611419565b6101bb7f000000000000000000000000e71306c6353bd8e282f77dbd3a06a357936b3bec81565b6040516001600160a01b039091168152602001610152565b6101bb7f00000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c5281281565b6101bb7f000000000000000000000000e61ebc2b9fd43bca89e38c707acb280907f447cb81565b61016466b1a2bc2ec5000081565b60035461024190610100900460ff1681565b6040519015158152602001610152565b61016462015f9081565b6101647f000000000000000000000000000000000000000000000000000000000000000181565b6101646706f05b59d3b2000081565b6001546101bb906001600160a01b031681565b6101646112c081565b6101647f0000000000000000000000000000000000c097ce7bc90715b34b9f100000000081565b600054600160a01b900460ff16610241565b6102f96102f4366004611452565b610733565b005b610164670de0b6b3a764000081565b61033260405180604001604052806009815260200168141c9a58d95199595960ba1b81525081565b604051610152919061146f565b6102f961034d3660046114bd565b6107e2565b6000546001600160a01b03166101bb565b60008061036e610a56565b9050600061038482600001518360200151610bce565b90506000610390610db1565b9050600060035460ff1660048111156103ab576103ab611403565b036104dc576103ba8383610e6f565b15610414576103c881610e90565b156103e1576103d76002610edd565b6000935050505090565b6103ea81610f3b565b156103f9576103d76001610edd565b6104036001610edd565b61040c81610f9a565b935050505090565b61041d83610fae565b1561045c5761042b81610e90565b1561043a576103d76004610edd565b6104446003610edd565b61044d81610f3b565b15610403576000935050505090565b6104668383610fd7565b156104b75761047481610e90565b15610483576103d76002610edd565b61048c81610f3b565b1561049b576103d76001610edd565b6104a58382611050565b156103f95761040c83604001516110e7565b6104c081610e90565b156104cf576104cf6004610edd565b61040c83604001516110e7565b600160035460ff1660048111156104f5576104f5611403565b036105445761050381610e90565b15610512576103d76002610edd565b61051b81610f3b565b1561052a576000935050505090565b6105358383836110f6565b15610403576104cf6000610edd565b600260035460ff16600481111561055d5761055d611403565b036105cb576001546001600160a01b03166105b15761057c8383610e6f565b15801561058f575061058d83610fae565b155b80156105a257506105a08383610fd7565b155b156103d7576104cf6004610edd565b6105bc8383836110f6565b156103d7576104cf6000610edd565b6003805460ff1660048111156105e3576105e3611403565b036106a0576105f28383610e6f565b156106195761060081610e90565b1561060f576103d76002610edd565b6104446001610edd565b61062283610fae565b1561063f5761063081610e90565b15610444576103d76004610edd565b6106498383610fd7565b156106575761060081610e90565b61066081610e90565b1561066f576104cf6004610edd565b61067881610f3b565b15610687576000935050505090565b6106918382611050565b156103f9576104cf6000610edd565b600460035460ff1660048111156106b9576106b9611403565b036103d7576106c88383610e6f565b156106d7576103d76002610edd565b6106e083610fae565b156106ef576000935050505090565b6106f98383610fd7565b15610708576103d76002610edd565b6107138383836110f6565b156104cf576001546001600160a01b0316156104cf576104cf6000610edd565b610749336000356001600160e01b031916611164565b61078f5760405162461bcd60e51b8152602060048201526012602482015271105d5d1a0e8815539055551213d49256915160721b60448201526064015b60405180910390fd5b6003805461ff001916610100831515021790556107aa6111fb565b6001600160a01b03167f0bf6cc51307ce9e3a6e5ff2f9281a57123273aff808032156de6990798c4eb9460405160405180910390a250565b6107f8336000356001600160e01b031916611164565b6108395760405162461bcd60e51b8152602060048201526012602482015271105d5d1a0e8815539055551213d49256915160721b6044820152606401610786565b604080516060810182526000808252602082018190529181019190915281906001600160a01b03831615610a0057816001600160a01b031663bbcb625f6040518163ffffffff1660e01b8152600401606060405180830381865afa9250505080156108c1575060408051601f3d908101601f191682019092526108be918101906114e6565b60015b61090d57826001600160a01b03167f8c32448b27b941b35da4a33f2afee2fdada7d1149551d0d4c28e7feeff3663064260405161090091815260200190565b60405180910390a2505050565b82845260208401829052801515604085015261092884610e90565b1580156109a1575061099f8460200151866001600160a01b0316634277bc066040518163ffffffff1660e01b8152600401602060405180830381865afa158015610976573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099a919061151f565b611257565b155b156109f857600180546001600160a01b038781166001600160a01b03198316179092556040519082169188169082907f633b20eaebf02bd523c44b01ff791580199b6217bae352f4cbdc95e1226fb55090600090a3505b505050505050565b600180546001600160a01b038481166001600160a01b03198316179092556040519082169185169082907f633b20eaebf02bd523c44b01ff791580199b6217bae352f4cbdc95e1226fb55090600090a350505050565b610a5e6113b9565b6000807f000000000000000000000000e61ebc2b9fd43bca89e38c707acb280907f447cb6001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015610adb575060408051601f3d908101601f19168201909252610ad891810190611554565b60015b610ae457505090565b506001600160501b0390931686525060608501919091529150610b056111fb565b6001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa925050508015610b5e575060408051601f3d908101601f19168201909252610b5b91810190611554565b60015b610b6757505090565b506001600160501b03909316602087015250608085019190915290508251610b8f908361126c565b8015610ba45750610ba483602001518261126c565b15610bbd57610bb3828261129f565b6040840152610bc2565b505090565b5050600160a082015290565b610bd66113b9565b6001600160501b0383161580610bf357506001600160501b038216155b610dab576000806001600160a01b037f000000000000000000000000e61ebc2b9fd43bca89e38c707acb280907f447cb16639a6fc8f5610c346001886115ba565b6040516001600160e01b031960e084901b1681526001600160501b03909116600482015260240160a060405180830381865afa925050508015610c94575060408051601f3d908101601f19168201909252610c9191810190611554565b60015b610c9f575050610dab565b506001600160501b0390931686525060608501919091529150610cc06111fb565b6001600160a01b0316639a6fc8f5610cd96001876115ba565b6040516001600160e01b031960e084901b1681526001600160501b03909116600482015260240160a060405180830381865afa925050508015610d39575060408051601f3d908101601f19168201909252610d3691810190611554565b60015b610d44575050610dab565b506001600160501b03909316602087015250608085019190915290508251610d6c908361126c565b8015610d815750610d8183602001518261126c565b15610d9a57610d90828261129f565b6040840152610da1565b5050610dab565b5050600160a08201525b92915050565b610dd7604051806060016040528060008152602001600081526020016000151581525090565b6001546001600160a01b031615610e6c57600160009054906101000a90046001600160a01b03166001600160a01b031663bbcb625f6040518163ffffffff1660e01b8152600401606060405180830381865afa925050508015610e57575060408051601f3d908101601f19168201909252610e54918101906114e6565b60015b15610e6c579183526020830152151560408201525b90565b6000610e7a83611314565b80610e895750610e8982611314565b9392505050565b60008160400151610ea357506001919050565b60208201511580610eb75750428260200151115b15610ec457506001919050565b8151600003610ed557506001919050565b506000919050565b6003805482919060ff19166001836004811115610efc57610efc611403565b02179055507f5c57579a8214fe4f710c1c56fa829f045b9fa6d225a744225a30c32188064d4e81604051610f309190611419565b60405180910390a150565b6000808260200151118015610dab57506020808301516001546040805163213bde0360e11b81529051610dab946001600160a01b0390931692634277bc0692600480820193918290030181865afa158015610976573d6000803e3d6000fd5b6000610fa98260000151611363565b505190565b6000610fc082606001516112c0611257565b80610dab5750610dab826080015162015f90611257565b600080610fec84604001518460400151611393565b90506000611002856040015185604001516113a9565b9050600080821161101457600061103c565b81670de0b6b3a764000061102885836115e1565b61103291906115f4565b61103c919061160b565b6706f05b59d3b20000109695505050505050565b6001546000906001600160a01b031661106b57506001610dab565b600061107f83600001518560400151611393565b905080600003611093576000915050610dab565b60006110a7846000015186604001516113a9565b9050600082670de0b6b3a76400006110bf82856115e1565b6110c991906115f4565b6110d3919061160b565b66b1a2bc2ec5000010159695505050505050565b60006110f282611363565b5090565b6001546000906001600160a01b031615801590611126575061111782610e90565b80611126575061112682610f3b565b8061113657506111368484610e6f565b80611145575061114584610fae565b1561115257506000610e89565b61115c8483611050565b949350505050565b600080546001600160a01b0316801580159061115c575060405163b700961360e01b81526001600160a01b0385811660048301523060248301526001600160e01b03198516604483015282169063b700961390606401602060405180830381865afa1580156111d7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115c919061162d565b600354600090610100900460ff1661123257507f000000000000000000000000e71306c6353bd8e282f77dbd3a06a357936b3bec90565b507f00000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c5281290565b60008161126484426115e1565b119392505050565b600080821361127d57506000610dab565b826001600160501b031660000361129657506000610dab565b50600192915050565b60007f0000000000000000000000000000000000c097ce7bc90715b34b9f1000000000670de0b6b3a7640000836112f6867f00000000000000000000000000000000000000000000000000000000000000016115f4565b61130091906115f4565b61130a91906115f4565b610e89919061160b565b60008160a0015161132757506001919050565b6060820151158061133b5750428260600151115b8061134857506080820151155b806113565750428260800151115b15610ed557506001919050565b6040518181527f4d29de21de555af78a62fc82dd4bc05e9ae5b0660a37f04729527e0f22780cd390602001610f30565b60008183106113a25781610e89565b5090919050565b6000818310156113a25781610e89565b6040518060c0016040528060006001600160501b0316815260200160006001600160501b031681526020016000815260200160008152602001600081526020016000151581525090565b634e487b7160e01b600052602160045260246000fd5b602081016005831061143b57634e487b7160e01b600052602160045260246000fd5b91905290565b801515811461144f57600080fd5b50565b60006020828403121561146457600080fd5b8135610e8981611441565b600060208083528351808285015260005b8181101561149c57858101830151858201604001528201611480565b506000604082860101526040601f19601f8301168501019250505092915050565b6000602082840312156114cf57600080fd5b81356001600160a01b0381168114610e8957600080fd5b6000806000606084860312156114fb57600080fd5b8351925060208401519150604084015161151481611441565b809150509250925092565b60006020828403121561153157600080fd5b5051919050565b80516001600160501b038116811461154f57600080fd5b919050565b600080600080600060a0868803121561156c57600080fd5b61157586611538565b945060208601519350604086015192506060860151915061159860808701611538565b90509295509295909350565b634e487b7160e01b600052601160045260246000fd5b6001600160501b038281168282160390808211156115da576115da6115a4565b5092915050565b81810381811115610dab57610dab6115a4565b8082028115828204841417610dab57610dab6115a4565b60008261162857634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121561163f57600080fd5b8151610e898161144156fea2646970667358221220128fcd3f494b5397341e7c92e1bcfcfaac459065cfaae5daa44c5b82a92b6b3b64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a095d44831c26cfb6acb806a6531ae3ca32dbc100000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c52812000000000000000000000000e61ebc2b9fd43bca89e38c707acb280907f447cb0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _fallbackCallerAddress (address): 0x0000000000000000000000000000000000000000
Arg [1] : _authorityAddress (address): 0x2A095d44831C26cFB6aCb806A6531AE3CA32DBc1
Arg [2] : _collEthCLFeed (address): 0x86392dC19c0b719886221c78AB11eb8Cf5c52812
Arg [3] : _ethBtcCLFeed (address): 0xE61EbC2B9Fd43bCA89E38c707aCb280907f447CB
Arg [4] : _useDynamicFeed (bool): False
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 0000000000000000000000002a095d44831c26cfb6acb806a6531ae3ca32dbc1
Arg [2] : 00000000000000000000000086392dc19c0b719886221c78ab11eb8cf5c52812
Arg [3] : 000000000000000000000000e61ebc2b9fd43bca89e38c707acb280907f447cb
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 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.