2020-05-29 16:45:37 +00:00
|
|
|
// SPDX-License-Identifier: agpl-3.0
|
2020-11-20 10:45:20 +00:00
|
|
|
pragma solidity 0.6.12;
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-10-15 13:41:56 +00:00
|
|
|
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
|
|
|
|
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
2020-06-02 14:16:22 +00:00
|
|
|
|
2020-08-20 10:44:51 +00:00
|
|
|
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
|
|
|
|
import {IChainlinkAggregator} from '../interfaces/IChainlinkAggregator.sol';
|
2020-10-15 13:41:56 +00:00
|
|
|
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-11-17 09:24:24 +00:00
|
|
|
/// @title AaveOracle
|
2020-05-29 16:45:37 +00:00
|
|
|
/// @author Aave
|
|
|
|
/// @notice Proxy smart contract to get the price of an asset from a price source, with Chainlink Aggregator
|
|
|
|
/// smart contracts as primary option
|
|
|
|
/// - If the returned price by a Chainlink aggregator is <= 0, the call is forwarded to a fallbackOracle
|
|
|
|
/// - Owned by the Aave governance system, allowed to add sources for assets, replace them
|
|
|
|
/// and change the fallbackOracle
|
2020-11-17 09:24:24 +00:00
|
|
|
contract AaveOracle is IPriceOracleGetter, Ownable {
|
2020-08-12 17:36:58 +00:00
|
|
|
using SafeERC20 for IERC20;
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2021-07-20 09:32:22 +00:00
|
|
|
event BaseCurrencySet(address indexed baseCurrency, uint256 baseCurrencyUnit);
|
2020-07-13 08:54:08 +00:00
|
|
|
event AssetSourceUpdated(address indexed asset, address indexed source);
|
|
|
|
event FallbackOracleUpdated(address indexed fallbackOracle);
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
mapping(address => IChainlinkAggregator) private assetsSources;
|
2020-08-21 12:00:10 +00:00
|
|
|
IPriceOracleGetter private _fallbackOracle;
|
2021-07-20 09:32:22 +00:00
|
|
|
address public immutable BASE_CURRENCY;
|
|
|
|
uint256 public immutable BASE_CURRENCY_UNIT;
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice Constructor
|
2020-08-21 12:00:10 +00:00
|
|
|
/// @param assets The addresses of the assets
|
|
|
|
/// @param sources The address of the source of each asset
|
|
|
|
/// @param fallbackOracle The address of the fallback oracle to use if the data of an
|
2020-07-13 08:54:08 +00:00
|
|
|
/// aggregator is not consistent
|
2021-07-20 09:32:22 +00:00
|
|
|
/// @param baseCurrency the base currency used for the price quotes. If USD is used, base currency is 0x0
|
|
|
|
/// @param baseCurrencyUnit the unit of the base currency
|
2020-07-13 08:54:08 +00:00
|
|
|
constructor(
|
2020-08-21 12:00:10 +00:00
|
|
|
address[] memory assets,
|
|
|
|
address[] memory sources,
|
2020-11-06 11:09:24 +00:00
|
|
|
address fallbackOracle,
|
2021-07-20 09:32:22 +00:00
|
|
|
address baseCurrency,
|
|
|
|
uint256 baseCurrencyUnit
|
2020-07-13 08:54:08 +00:00
|
|
|
) public {
|
2020-08-21 12:00:10 +00:00
|
|
|
_setFallbackOracle(fallbackOracle);
|
|
|
|
_setAssetsSources(assets, sources);
|
2021-07-20 09:32:22 +00:00
|
|
|
BASE_CURRENCY = baseCurrency;
|
|
|
|
BASE_CURRENCY_UNIT = baseCurrencyUnit;
|
|
|
|
emit BaseCurrencySet(baseCurrency, baseCurrencyUnit);
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice External function called by the Aave governance to set or replace sources of assets
|
2020-08-21 12:00:10 +00:00
|
|
|
/// @param assets The addresses of the assets
|
|
|
|
/// @param sources The address of the source of each asset
|
|
|
|
function setAssetSources(address[] calldata assets, address[] calldata sources)
|
2020-07-13 08:54:08 +00:00
|
|
|
external
|
|
|
|
onlyOwner
|
|
|
|
{
|
2020-08-21 12:00:10 +00:00
|
|
|
_setAssetsSources(assets, sources);
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice Sets the fallbackOracle
|
|
|
|
/// - Callable only by the Aave governance
|
2020-08-21 12:00:10 +00:00
|
|
|
/// @param fallbackOracle The address of the fallbackOracle
|
|
|
|
function setFallbackOracle(address fallbackOracle) external onlyOwner {
|
|
|
|
_setFallbackOracle(fallbackOracle);
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice Internal function to set the sources for each asset
|
2020-08-21 12:00:10 +00:00
|
|
|
/// @param assets The addresses of the assets
|
|
|
|
/// @param sources The address of the source of each asset
|
|
|
|
function _setAssetsSources(address[] memory assets, address[] memory sources) internal {
|
|
|
|
require(assets.length == sources.length, 'INCONSISTENT_PARAMS_LENGTH');
|
|
|
|
for (uint256 i = 0; i < assets.length; i++) {
|
|
|
|
assetsSources[assets[i]] = IChainlinkAggregator(sources[i]);
|
|
|
|
emit AssetSourceUpdated(assets[i], sources[i]);
|
2020-05-29 16:45:37 +00:00
|
|
|
}
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice Internal function to set the fallbackOracle
|
2020-08-21 12:00:10 +00:00
|
|
|
/// @param fallbackOracle The address of the fallbackOracle
|
|
|
|
function _setFallbackOracle(address fallbackOracle) internal {
|
|
|
|
_fallbackOracle = IPriceOracleGetter(fallbackOracle);
|
|
|
|
emit FallbackOracleUpdated(fallbackOracle);
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice Gets an asset price by address
|
2020-08-21 12:00:10 +00:00
|
|
|
/// @param asset The asset address
|
2021-01-27 14:43:34 +00:00
|
|
|
function getAssetPrice(address asset) public view override returns (uint256) {
|
2020-08-21 12:00:10 +00:00
|
|
|
IChainlinkAggregator source = assetsSources[asset];
|
2020-11-06 11:09:24 +00:00
|
|
|
|
2021-07-20 09:32:22 +00:00
|
|
|
if (asset == BASE_CURRENCY) {
|
|
|
|
return BASE_CURRENCY_UNIT;
|
2020-11-06 11:09:24 +00:00
|
|
|
} else if (address(source) == address(0)) {
|
2020-08-21 12:00:10 +00:00
|
|
|
return _fallbackOracle.getAssetPrice(asset);
|
2020-08-20 10:44:51 +00:00
|
|
|
} else {
|
2020-08-21 12:00:10 +00:00
|
|
|
int256 price = IChainlinkAggregator(source).latestAnswer();
|
|
|
|
if (price > 0) {
|
|
|
|
return uint256(price);
|
2020-07-13 08:54:08 +00:00
|
|
|
} else {
|
2020-08-21 12:00:10 +00:00
|
|
|
return _fallbackOracle.getAssetPrice(asset);
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-08-20 10:44:51 +00:00
|
|
|
}
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice Gets a list of prices from a list of assets addresses
|
2020-08-21 12:00:10 +00:00
|
|
|
/// @param assets The list of assets addresses
|
|
|
|
function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory) {
|
|
|
|
uint256[] memory prices = new uint256[](assets.length);
|
|
|
|
for (uint256 i = 0; i < assets.length; i++) {
|
|
|
|
prices[i] = getAssetPrice(assets[i]);
|
2020-05-29 16:45:37 +00:00
|
|
|
}
|
2020-07-13 08:54:08 +00:00
|
|
|
return prices;
|
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice Gets the address of the source for an asset address
|
2020-08-21 12:00:10 +00:00
|
|
|
/// @param asset The address of the asset
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @return address The address of the source
|
2020-08-21 12:00:10 +00:00
|
|
|
function getSourceOfAsset(address asset) external view returns (address) {
|
|
|
|
return address(assetsSources[asset]);
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-05-29 16:45:37 +00:00
|
|
|
|
2020-07-13 08:54:08 +00:00
|
|
|
/// @notice Gets the address of the fallback oracle
|
|
|
|
/// @return address The addres of the fallback oracle
|
|
|
|
function getFallbackOracle() external view returns (address) {
|
2020-08-21 12:00:10 +00:00
|
|
|
return address(_fallbackOracle);
|
2020-07-13 08:54:08 +00:00
|
|
|
}
|
2020-06-02 14:16:22 +00:00
|
|
|
}
|