aave-protocol-v2/contracts/misc/ChainlinkProxyPriceProvider.sol

116 lines
4.7 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.8;
2020-08-20 10:44:51 +00:00
import {Ownable} from '@openzeppelin/contracts/access/Ownable.sol';
import {IERC20} from '@openzeppelin/contracts/token/ERC20/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-08-12 17:36:58 +00:00
import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
/// @title ChainlinkProxyPriceProvider
/// @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
contract ChainlinkProxyPriceProvider is IPriceOracleGetter, Ownable {
2020-08-12 17:36:58 +00:00
using SafeERC20 for IERC20;
2020-07-13 08:54:08 +00:00
event AssetSourceUpdated(address indexed asset, address indexed source);
event FallbackOracleUpdated(address indexed fallbackOracle);
2020-07-13 08:54:08 +00:00
mapping(address => IChainlinkAggregator) private assetsSources;
IPriceOracleGetter private fallbackOracle;
2020-07-13 08:54:08 +00:00
/// @notice Constructor
/// @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
/// aggregator is not consistent
constructor(
address[] memory _assets,
address[] memory _sources,
address _fallbackOracle
) public {
internalSetFallbackOracle(_fallbackOracle);
internalSetAssetsSources(_assets, _sources);
}
2020-07-13 08:54:08 +00:00
/// @notice External function called by the Aave governance to set or replace sources of assets
/// @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)
external
onlyOwner
{
internalSetAssetsSources(_assets, _sources);
}
2020-07-13 08:54:08 +00:00
/// @notice Sets the fallbackOracle
/// - Callable only by the Aave governance
/// @param _fallbackOracle The address of the fallbackOracle
function setFallbackOracle(address _fallbackOracle) external onlyOwner {
internalSetFallbackOracle(_fallbackOracle);
}
2020-07-13 08:54:08 +00:00
/// @notice Internal function to set the sources for each asset
/// @param _assets The addresses of the assets
/// @param _sources The address of the source of each asset
function internalSetAssetsSources(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-07-13 08:54:08 +00:00
}
2020-07-13 08:54:08 +00:00
/// @notice Internal function to set the fallbackOracle
/// @param _fallbackOracle The address of the fallbackOracle
function internalSetFallbackOracle(address _fallbackOracle) internal {
fallbackOracle = IPriceOracleGetter(_fallbackOracle);
emit FallbackOracleUpdated(_fallbackOracle);
}
2020-07-13 08:54:08 +00:00
/// @notice Gets an asset price by address
/// @param _asset The asset address
function getAssetPrice(address _asset) public override view returns (uint256) {
IChainlinkAggregator source = assetsSources[_asset];
2020-08-20 10:44:51 +00:00
// If there is no registered source for the asset, call the fallbackOracle
if (address(source) == address(0)) {
return IPriceOracleGetter(fallbackOracle).getAssetPrice(_asset);
} else {
int256 _price = IChainlinkAggregator(source).latestAnswer();
if (_price > 0) {
return uint256(_price);
2020-07-13 08:54:08 +00:00
} else {
2020-08-20 10:44:51 +00:00
return IPriceOracleGetter(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-07-13 08:54:08 +00:00
/// @notice Gets a list of prices from a list of assets addresses
/// @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-07-13 08:54:08 +00:00
return prices;
}
2020-07-13 08:54:08 +00:00
/// @notice Gets the address of the source for an asset address
/// @param _asset The address of the asset
/// @return address The address of the source
function getSourceOfAsset(address _asset) external view returns (address) {
return address(assetsSources[_asset]);
}
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) {
return address(fallbackOracle);
}
2020-06-02 14:16:22 +00:00
}