Contract Name:
ChainlinkPriceOracleV1
Contract Source Code:
/*
Copyright 2020 Dolomite.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.7;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "../../protocol/interfaces/IPriceOracle.sol";
import "../../protocol/lib/Monetary.sol";
import "../../protocol/lib/Require.sol";
import "../interfaces/IChainlinkAggregator.sol";
import "./IChainlinkFlags.sol";
/**
* @title ChainlinkPriceOracleV1
* @author Dolomite
*
* An implementation of the IPriceOracle interface that makes Chainlink prices compatible with the protocol.
*/
contract ChainlinkPriceOracleV1 is IPriceOracle, Ownable {
using SafeMath for uint;
bytes32 private constant FILE = "ChainlinkPriceOracleV1";
// solium-disable-next-line max-len
address constant private FLAG_ARBITRUM_SEQ_OFFLINE = address(bytes20(bytes32(uint256(keccak256("chainlink.flags.arbitrum-seq-offline")) - 1)));
event TokenInsertedOrUpdated(
address indexed token,
address indexed aggregator,
address indexed tokenPair
);
mapping(address => IChainlinkAggregator) public tokenToAggregatorMap;
mapping(address => uint8) public tokenToDecimalsMap;
/// Defaults to USD if the value is the ZERO address
mapping(address => address) public tokenToPairingMap;
/// Should defaults to CHAINLINK_USD_DECIMALS when value is empty
mapping(address => uint8) public tokenToAggregatorDecimalsMap;
IChainlinkFlags public chainlinkFlags;
uint8 public CHAINLINK_USD_DECIMALS = 8;
uint8 public CHAINLINK_ETH_DECIMALS = 18;
/**
* Note, these arrays are set up, such that each index corresponds with one-another.
*
* @param tokens The tokens that are supported by this adapter.
* @param chainlinkAggregators The Chainlink aggregators that have on-chain prices.
* @param tokenDecimals The number of decimals that each token has.
* @param tokenPairs The token against which this token's value is compared using the aggregator. The
* zero address means USD.
* @param aggregatorDecimals The number of decimals that the value has that comes back from the corresponding
* Chainlink Aggregator.
* @param chainlinkFlagsOrNull The contract for layer-2 that denotes whether or not Chainlink oracles are currently
* offline, meaning data is stale and any critical operations should *not* occur. If
* not on layer 2, this value can be set to `address(0)`.
*/
constructor(
address[] memory tokens,
address[] memory chainlinkAggregators,
uint8[] memory tokenDecimals,
address[] memory tokenPairs,
uint8[] memory aggregatorDecimals,
address chainlinkFlagsOrNull
) public {
require( // coverage-disable-line
tokens.length == chainlinkAggregators.length,
"invalid aggregators"
);
require( // coverage-disable-line
chainlinkAggregators.length == tokenDecimals.length,
"invalid token decimals"
);
require( // coverage-disable-line
tokenDecimals.length == tokenPairs.length,
"invalid token pairs"
);
require( // coverage-disable-line
tokenPairs.length == aggregatorDecimals.length,
"invalid aggregator decimals"
);
for (uint i = 0; i < tokens.length; i++) {
_insertOrUpdateOracleToken(
tokens[i],
tokenDecimals[i],
chainlinkAggregators[i],
aggregatorDecimals[i],
tokenPairs[i]
);
}
chainlinkFlags = IChainlinkFlags(chainlinkFlagsOrNull);
}
// ============ Admin Functions ============
function insertOrUpdateOracleToken(
address token,
uint8 tokenDecimals,
address chainlinkAggregator,
uint8 aggregatorDecimals,
address tokenPair
) public onlyOwner {
_insertOrUpdateOracleToken(
token,
tokenDecimals,
chainlinkAggregator,
aggregatorDecimals,
tokenPair
);
}
// ============ Public Functions ============
function getPrice(
address token
)
public
view
returns (Monetary.Price memory) {
Require.that(
address(tokenToAggregatorMap[token]) != address(0),
FILE,
"invalid token",
token
);
IChainlinkFlags _chainlinkFlags = chainlinkFlags;
if (address(_chainlinkFlags) != address(0)) {
// https://docs.chain.link/docs/l2-sequencer-flag/
bool isFlagRaised = _chainlinkFlags.getFlag(FLAG_ARBITRUM_SEQ_OFFLINE);
Require.that(
!isFlagRaised,
FILE,
"Chainlink price oracles offline"
);
}
uint rawChainlinkPrice = uint(tokenToAggregatorMap[token].latestAnswer());
address tokenPair = tokenToPairingMap[token];
// standardize the Chainlink price to be the proper number of decimals of (36 - tokenDecimals)
uint standardizedPrice = standardizeNumberOfDecimals(
tokenToDecimalsMap[token],
rawChainlinkPrice,
tokenPair == address(0) ? CHAINLINK_USD_DECIMALS : tokenToAggregatorDecimalsMap[token]
);
if (tokenPair == address(0)) {
// The pair has a USD base, we are done.
return Monetary.Price({value : standardizedPrice});
} else {
// The price we just got and converted is NOT against USD. So we need to get its pair's price against USD.
// We can do so by recursively calling #getPrice using the `tokenPair` as the parameter instead of `token`.
uint tokenPairStandardizedPrice = getPrice(tokenPair).value;
// Standardize the price to use 36 decimals.
uint tokenPairWith36Decimals = tokenPairStandardizedPrice.mul(10 ** uint(tokenToDecimalsMap[tokenPair]));
// Now that the chained price uses 36 decimals (and thus is standardized), we can do easy math.
return Monetary.Price({value : standardizedPrice.mul(tokenPairWith36Decimals).div(ONE_DOLLAR)});
}
}
/**
* Standardizes `value` to have `ONE_DOLLAR` - `tokenDecimals` number of decimals.
*/
function standardizeNumberOfDecimals(
uint8 tokenDecimals,
uint value,
uint8 valueDecimals
) public pure returns (uint) {
uint tokenDecimalsFactor = 10 ** uint(tokenDecimals);
uint priceFactor = IPriceOracle.ONE_DOLLAR.div(tokenDecimalsFactor);
uint valueFactor = 10 ** uint(valueDecimals);
return value.mul(priceFactor).div(valueFactor);
}
// ============ Internal Functions ============
function _insertOrUpdateOracleToken(
address token,
uint8 tokenDecimals,
address chainlinkAggregator,
uint8 aggregatorDecimals,
address tokenPair
) internal {
tokenToAggregatorMap[token] = IChainlinkAggregator(chainlinkAggregator);
tokenToDecimalsMap[token] = tokenDecimals;
if (tokenPair != address(0)) {
// The aggregator's price is NOT against USD. Therefore, we need to store what it's against as well as the
// # of decimals the aggregator's price has.
tokenToPairingMap[token] = tokenPair;
tokenToAggregatorDecimalsMap[token] = aggregatorDecimals;
}
emit TokenInsertedOrUpdated(token, chainlinkAggregator, tokenPair);
}
}
pragma solidity ^0.5.0;
import "../GSN/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
pragma solidity ^0.5.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* _Available since v2.4.0._
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @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) {
// 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 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts 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.
*
* _Available since v2.4.0._
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts 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 mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message 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.
*
* _Available since v2.4.0._
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
pragma solidity ^0.5.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
contract Context {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () internal { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
/*
Copyright 2019 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.7;
pragma experimental ABIEncoderV2;
/**
* @title Require
* @author dYdX
*
* Stringifies parameters to pretty-print revert messages. Costs more gas than regular require()
*/
library Require {
// ============ Constants ============
uint256 constant ASCII_ZERO = 48; // '0'
uint256 constant ASCII_RELATIVE_ZERO = 87; // 'a' - 10
uint256 constant ASCII_LOWER_EX = 120; // 'x'
bytes2 constant COLON = 0x3a20; // ': '
bytes2 constant COMMA = 0x2c20; // ', '
bytes2 constant LPAREN = 0x203c; // ' <'
byte constant RPAREN = 0x3e; // '>'
uint256 constant FOUR_BIT_MASK = 0xf;
// ============ Library Functions ============
function that(
bool must,
bytes32 file,
bytes32 reason
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason)
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
uint256 payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
uint256 payloadA,
uint256 payloadB
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
COMMA,
stringify(payloadB),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA,
uint256 payloadB
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
COMMA,
stringify(payloadB),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
address payloadA,
uint256 payloadB,
uint256 payloadC
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
COMMA,
stringify(payloadB),
COMMA,
stringify(payloadC),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
bytes32 payloadA
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
RPAREN
)
)
);
}
}
function that(
bool must,
bytes32 file,
bytes32 reason,
bytes32 payloadA,
uint256 payloadB,
uint256 payloadC
)
internal
pure
{
if (!must) {
revert(
string(
abi.encodePacked(
stringifyTruncated(file),
COLON,
stringifyTruncated(reason),
LPAREN,
stringify(payloadA),
COMMA,
stringify(payloadB),
COMMA,
stringify(payloadC),
RPAREN
)
)
);
}
}
// ============ Private Functions ============
function stringifyTruncated(
bytes32 input
)
private
pure
returns (bytes memory)
{
// put the input bytes into the result
bytes memory result = abi.encodePacked(input);
// determine the length of the input by finding the location of the last non-zero byte
for (uint256 i = 32; i > 0; ) {
// reverse-for-loops with unsigned integer
/* solium-disable-next-line security/no-modify-for-iter-var */
i--;
// find the last non-zero byte in order to determine the length
if (result[i] != 0) {
uint256 length = i + 1;
/* solium-disable-next-line security/no-inline-assembly */
assembly {
mstore(result, length) // r.length = length;
}
return result;
}
}
// all bytes are zero
return new bytes(0);
}
function stringify(
uint256 input
)
private
pure
returns (bytes memory)
{
if (input == 0) {
return "0";
}
// get the final string length
uint256 j = input;
uint256 length;
while (j != 0) {
length++;
j /= 10;
}
// allocate the string
bytes memory bstr = new bytes(length);
// populate the string starting with the least-significant character
j = input;
for (uint256 i = length; i > 0; ) {
// reverse-for-loops with unsigned integer
/* solium-disable-next-line security/no-modify-for-iter-var */
i--;
// take last decimal digit
bstr[i] = byte(uint8(ASCII_ZERO + (j % 10)));
// remove the last decimal digit
j /= 10;
}
return bstr;
}
function stringify(
address input
)
private
pure
returns (bytes memory)
{
uint256 z = uint256(input);
// addresses are "0x" followed by 20 bytes of data which take up 2 characters each
bytes memory result = new bytes(42);
// populate the result with "0x"
result[0] = byte(uint8(ASCII_ZERO));
result[1] = byte(uint8(ASCII_LOWER_EX));
// for each byte (starting from the lowest byte), populate the result with two characters
for (uint256 i = 0; i < 20; i++) {
// each byte takes two characters
uint256 shift = i * 2;
// populate the least-significant character
result[41 - shift] = char(z & FOUR_BIT_MASK);
z = z >> 4;
// populate the most-significant character
result[40 - shift] = char(z & FOUR_BIT_MASK);
z = z >> 4;
}
return result;
}
function stringify(
bytes32 input
)
private
pure
returns (bytes memory)
{
uint256 z = uint256(input);
// bytes32 are "0x" followed by 32 bytes of data which take up 2 characters each
bytes memory result = new bytes(66);
// populate the result with "0x"
result[0] = byte(uint8(ASCII_ZERO));
result[1] = byte(uint8(ASCII_LOWER_EX));
// for each byte (starting from the lowest byte), populate the result with two characters
for (uint256 i = 0; i < 32; i++) {
// each byte takes two characters
uint256 shift = i * 2;
// populate the least-significant character
result[65 - shift] = char(z & FOUR_BIT_MASK);
z = z >> 4;
// populate the most-significant character
result[64 - shift] = char(z & FOUR_BIT_MASK);
z = z >> 4;
}
return result;
}
function char(
uint256 input
)
private
pure
returns (byte)
{
// return ASCII digit (0-9)
if (input < 10) {
return byte(uint8(input + ASCII_ZERO));
}
// return ASCII letter (a-f)
return byte(uint8(input + ASCII_RELATIVE_ZERO));
}
}
/*
Copyright 2019 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.7;
pragma experimental ABIEncoderV2;
/**
* @title Monetary
* @author dYdX
*
* Library for types involving money
*/
library Monetary {
/*
* The price of a base-unit of an asset. Has `36 - token.decimals` decimals
*/
struct Price {
uint256 value;
}
/*
* Total value of an some amount of an asset. Equal to (price * amount). Has 36 decimals.
*/
struct Value {
uint256 value;
}
}
/*
Copyright 2019 dYdX Trading Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.7;
pragma experimental ABIEncoderV2;
import { Monetary } from "../lib/Monetary.sol";
/**
* @title IPriceOracle
* @author dYdX
*
* Interface that Price Oracles for DolomiteMargin must implement in order to report prices.
*/
contract IPriceOracle {
// ============ Constants ============
uint256 public constant ONE_DOLLAR = 10 ** 36;
// ============ Public Functions ============
/**
* Get the price of a token
*
* @param token The ERC20 token address of the market
* @return The USD price of a base unit of the token, then multiplied by 10^36.
* So a USD-stable coin with 18 decimal places would return 10^18.
* This is the price of the base unit rather than the price of a "human-readable"
* token amount. Every ERC20 may have a different number of decimals.
*/
function getPrice(
address token
)
public
view
returns (Monetary.Price memory);
}
/*
Copyright 2022 Dolomite.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.7;
/**
* @title IChainlinkFlags
* @author Dolomite
*/
interface IChainlinkFlags {
function getFlag(address subject) external view returns (bool);
}
/*
Copyright 2020 Dolomite.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity ^0.5.7;
pragma experimental ABIEncoderV2;
/**
* @title IChainlinkAggregator
* @author Dolomite
*
* Gets the latest price from the Chainlink Oracle Network. Amount of decimals depends on the base.
*/
contract IChainlinkAggregator {
function latestAnswer() public view returns (int256);
}