aave-oracle

Created Diff never expires
10 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
122 lines
16 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
128 lines
// SPDX-License-Identifier: agpl-3.0
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma solidity 0.6.12;


import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';


import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IChainlinkAggregator} from '../interfaces/IChainlinkAggregator.sol';
import {IChainlinkAggregator} from '../interfaces/IChainlinkAggregator.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';


/// @title AaveOracle
/// @title AaveOracle
/// @author Aave
/// @author Aave
/// @notice Proxy smart contract to get the price of an asset from a price source, with Chainlink Aggregator
/// @notice Proxy smart contract to get the price of an asset from a price source, with Chainlink Aggregator
/// smart contracts as primary option
/// smart contracts as primary option
/// - If the returned price by a Chainlink aggregator is <= 0, the call is forwarded to a fallbackOracle
/// - 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
/// - Owned by the Aave governance system, allowed to add sources for assets, replace them
/// and change the fallbackOracle
/// and change the fallbackOracle
contract AaveOracle is IPriceOracleGetter, Ownable {
contract AaveOracle is IPriceOracleGetter, Ownable {
using SafeERC20 for IERC20;
using SafeERC20 for IERC20;


event WethSet(address indexed weth);
event BaseCurrencySet(address indexed baseCurrency, uint256 baseCurrencyUnit);
event AssetSourceUpdated(address indexed asset, address indexed source);
event AssetSourceUpdated(address indexed asset, address indexed source);
event FallbackOracleUpdated(address indexed fallbackOracle);
event FallbackOracleUpdated(address indexed fallbackOracle);


mapping(address => IChainlinkAggregator) private assetsSources;
mapping(address => IChainlinkAggregator) private assetsSources;
IPriceOracleGetter private _fallbackOracle;
IPriceOracleGetter private _fallbackOracle;
address public immutable WETH;
address public immutable BASE_CURRENCY;
uint256 public immutable BASE_CURRENCY_UNIT;


/// @notice Constructor
/// @notice Constructor
/// @param assets The addresses of the assets
/// @param assets The addresses of the assets
/// @param sources The address of the source of each asset
/// @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
/// @param fallbackOracle The address of the fallback oracle to use if the data of an
/// aggregator is not consistent
/// aggregator is not consistent
/// @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
constructor(
constructor(
address[] memory assets,
address[] memory assets,
address[] memory sources,
address[] memory sources,
address fallbackOracle,
address fallbackOracle,
address weth
address baseCurrency,
uint256 baseCurrencyUnit
) public {
) public {
_setFallbackOracle(fallbackOracle);
_setFallbackOracle(fallbackOracle);
_setAssetsSources(assets, sources);
_setAssetsSources(assets, sources);
WETH = weth;
BASE_CURRENCY = baseCurrency;
emit WethSet(weth);
BASE_CURRENCY_UNIT = baseCurrencyUnit;
emit BaseCurrencySet(baseCurrency, baseCurrencyUnit);
}
}


/// @notice External function called by the Aave governance to set or replace sources of assets
/// @notice External function called by the Aave governance to set or replace sources of assets
/// @param assets The addresses of the assets
/// @param assets The addresses of the assets
/// @param sources The address of the source of each asset
/// @param sources The address of the source of each asset
function setAssetSources(address[] calldata assets, address[] calldata sources)
function setAssetSources(address[] calldata assets, address[] calldata sources)
external
external
onlyOwner
onlyOwner
{
{
_setAssetsSources(assets, sources);
_setAssetsSources(assets, sources);
}
}


/// @notice Sets the fallbackOracle
/// @notice Sets the fallbackOracle
/// - Callable only by the Aave governance
/// - Callable only by the Aave governance
/// @param fallbackOracle The address of the fallbackOracle
/// @param fallbackOracle The address of the fallbackOracle
function setFallbackOracle(address fallbackOracle) external onlyOwner {
function setFallbackOracle(address fallbackOracle) external onlyOwner {
_setFallbackOracle(fallbackOracle);
_setFallbackOracle(fallbackOracle);
}
}


/// @notice Internal function to set the sources for each asset
/// @notice Internal function to set the sources for each asset
/// @param assets The addresses of the assets
/// @param assets The addresses of the assets
/// @param sources The address of the source of each asset
/// @param sources The address of the source of each asset
function _setAssetsSources(address[] memory assets, address[] memory sources) internal {
function _setAssetsSources(address[] memory assets, address[] memory sources) internal {
require(assets.length == sources.length, 'INCONSISTENT_PARAMS_LENGTH');
require(assets.length == sources.length, 'INCONSISTENT_PARAMS_LENGTH');
for (uint256 i = 0; i < assets.length; i++) {
for (uint256 i = 0; i < assets.length; i++) {
assetsSources[assets[i]] = IChainlinkAggregator(sources[i]);
assetsSources[assets[i]] = IChainlinkAggregator(sources[i]);
emit AssetSourceUpdated(assets[i], sources[i]);
emit AssetSourceUpdated(assets[i], sources[i]);
}
}
}
}


/// @notice Internal function to set the fallbackOracle
/// @notice Internal function to set the fallbackOracle
/// @param fallbackOracle The address of the fallbackOracle
/// @param fallbackOracle The address of the fallbackOracle
function _setFallbackOracle(address fallbackOracle) internal {
function _setFallbackOracle(address fallbackOracle) internal {
_fallbackOracle = IPriceOracleGetter(fallbackOracle);
_fallbackOracle = IPriceOracleGetter(fallbackOracle);
emit FallbackOracleUpdated(fallbackOracle);
emit FallbackOracleUpdated(fallbackOracle);
}
}


/// @notice Gets an asset price by address
/// @notice Gets an asset price by address
/// @param asset The asset address
/// @param asset The asset address
function getAssetPrice(address asset) public override view returns (uint256) {
function getAssetPrice(address asset) public view override returns (uint256) {
IChainlinkAggregator source = assetsSources[asset];
IChainlinkAggregator source = assetsSources[asset];


if (asset == WETH) {
if (asset == BASE_CURRENCY) {
return 1 ether;
return BASE_CURRENCY_UNIT;
} else if (address(source) == address(0)) {
} else if (address(source) == address(0)) {
return _fallbackOracle.getAssetPrice(asset);
return _fallbackOracle.getAssetPrice(asset);
} else {
} else {
int256 price = IChainlinkAggregator(source).latestAnswer();
int256 price = IChainlinkAggregator(source).latestAnswer();
if (price > 0) {
if (price > 0) {
return uint256(price);
return uint256(price);
} else {
} else {
return _fallbackOracle.getAssetPrice(asset);
return _fallbackOracle.getAssetPrice(asset);
}
}
}
}
}
}


/// @notice Gets a list of prices from a list of assets addresses
/// @notice Gets a list of prices from a list of assets addresses
/// @param assets The list of assets addresses
/// @param assets The list of assets addresses
function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory) {
function getAssetsPrices(address[] calldata assets) external view returns (uint256[] memory) {
uint256[] memory prices = new uint256[](assets.length);
uint256[] memory prices = new uint256[](assets.length);
for (uint256 i = 0; i < assets.length; i++) {
for (uint256 i = 0; i < assets.length; i++) {
prices[i] = getAssetPrice(assets[i]);
prices[i] = getAssetPrice(assets[i]);
}
}
return prices;
return prices;
}
}


/// @notice Gets the address of the source for an asset address
/// @notice Gets the address of the source for an asset address
/// @param asset The address of the asset
/// @param asset The address of the asset
/// @return address The address of the source
/// @return address The address of the source
function getSourceOfAsset(address asset) external view returns (address) {
function getSourceOfAsset(address asset) external view returns (address) {
return address(assetsSources[asset]);
return address(assetsSources[asset]);
}
}


/// @notice Gets the address of the fallback oracle
/// @notice Gets the address of the fallback oracle
/// @return address The addres of the fallback oracle
/// @return address The addres of the fallback oracle
function getFallbackOracle() external view returns (address) {
function getFallbackOracle() external view returns (address) {
return address(_fallbackOracle);
return address(_fallbackOracle);
}
}
}
}