Branch data Line data Source code
1 : : // SPDX-License-Identifier: MIT
2 : : pragma solidity ^0.8.10;
3 : :
4 : : import {AggregatorInterface} from '../dependencies/chainlink/AggregatorInterface.sol';
5 : : import {Errors} from '../protocol/libraries/helpers/Errors.sol';
6 : : import {IACLManager} from '../interfaces/IACLManager.sol';
7 : : import {IPoolAddressesProvider} from '../interfaces/IPoolAddressesProvider.sol';
8 : : import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
9 : : import {IAaveOracle} from '../interfaces/IAaveOracle.sol';
10 : :
11 : : /**
12 : : * @title AaveOracle
13 : : * @author Aave
14 : : * @notice Contract to get asset prices, manage price sources and update the fallback oracle
15 : : * - Use of Chainlink Aggregators as first source of price
16 : : * - If the returned price by a Chainlink aggregator is <= 0, the call is forwarded to a fallback oracle
17 : : * - Owned by the Aave governance
18 : : */
19 : : contract AaveOracle is IAaveOracle {
20 : : IPoolAddressesProvider public immutable ADDRESSES_PROVIDER;
21 : :
22 : : // Map of asset price sources (asset => priceSource)
23 : : mapping(address => AggregatorInterface) private assetsSources;
24 : :
25 : : IPriceOracleGetter private _fallbackOracle;
26 : : address public immutable override BASE_CURRENCY;
27 : : uint256 public immutable override BASE_CURRENCY_UNIT;
28 : :
29 : : /**
30 : : * @dev Only asset listing or pool admin can call functions marked by this modifier.
31 : : */
32 : : modifier onlyAssetListingOrPoolAdmins() {
33 : 4 : _onlyAssetListingOrPoolAdmins();
34 : : _;
35 : : }
36 : :
37 : : /**
38 : : * @notice Constructor
39 : : * @param provider The address of the new PoolAddressesProvider
40 : : * @param assets The addresses of the assets
41 : : * @param sources The address of the source of each asset
42 : : * @param fallbackOracle The address of the fallback oracle to use if the data of an
43 : : * aggregator is not consistent
44 : : * @param baseCurrency The base currency used for the price quotes. If USD is used, base currency is 0x0
45 : : * @param baseCurrencyUnit The unit of the base currency
46 : : */
47 : : constructor(
48 : : IPoolAddressesProvider provider,
49 : : address[] memory assets,
50 : : address[] memory sources,
51 : : address fallbackOracle,
52 : : address baseCurrency,
53 : : uint256 baseCurrencyUnit
54 : : ) {
55 : 0 : ADDRESSES_PROVIDER = provider;
56 : 0 : _setFallbackOracle(fallbackOracle);
57 : 0 : _setAssetsSources(assets, sources);
58 : 0 : BASE_CURRENCY = baseCurrency;
59 : 0 : BASE_CURRENCY_UNIT = baseCurrencyUnit;
60 : 0 : emit BaseCurrencySet(baseCurrency, baseCurrencyUnit);
61 : : }
62 : :
63 : : /// @inheritdoc IAaveOracle
64 : : function setAssetSources(
65 : : address[] calldata assets,
66 : : address[] calldata sources
67 : : ) external override onlyAssetListingOrPoolAdmins {
68 : 659 : _setAssetsSources(assets, sources);
69 : : }
70 : :
71 : : /// @inheritdoc IAaveOracle
72 : : function setFallbackOracle(
73 : : address fallbackOracle
74 : : ) external override onlyAssetListingOrPoolAdmins {
75 : 4 : _setFallbackOracle(fallbackOracle);
76 : : }
77 : :
78 : : /**
79 : : * @notice Internal function to set the sources for each asset
80 : : * @param assets The addresses of the assets
81 : : * @param sources The address of the source of each asset
82 : : */
83 : : function _setAssetsSources(address[] memory assets, address[] memory sources) internal {
84 : 659 : require(assets.length == sources.length, Errors.INCONSISTENT_PARAMS_LENGTH);
85 : 658 : for (uint256 i = 0; i < assets.length; i++) {
86 : 1954 : assetsSources[assets[i]] = AggregatorInterface(sources[i]);
87 : 1954 : emit AssetSourceUpdated(assets[i], sources[i]);
88 : : }
89 : : }
90 : :
91 : : /**
92 : : * @notice Internal function to set the fallback oracle
93 : : * @param fallbackOracle The address of the fallback oracle
94 : : */
95 : : function _setFallbackOracle(address fallbackOracle) internal {
96 : 4 : _fallbackOracle = IPriceOracleGetter(fallbackOracle);
97 : 4 : emit FallbackOracleUpdated(fallbackOracle);
98 : : }
99 : :
100 : : /// @inheritdoc IPriceOracleGetter
101 : : function getAssetPrice(address asset) public view override returns (uint256) {
102 : 111432 : AggregatorInterface source = assetsSources[asset];
103 : :
104 : 111432 : if (asset == BASE_CURRENCY) {
105 : 2 : return BASE_CURRENCY_UNIT;
106 : 111430 : } else if (address(source) == address(0)) {
107 : 3 : return _fallbackOracle.getAssetPrice(asset);
108 : : } else {
109 : 111427 : int256 price = source.latestAnswer();
110 : 111427 : if (price > 0) {
111 : 111424 : return uint256(price);
112 : : } else {
113 : 3 : return _fallbackOracle.getAssetPrice(asset);
114 : : }
115 : : }
116 : : }
117 : :
118 : : /// @inheritdoc IAaveOracle
119 : : function getAssetsPrices(
120 : : address[] calldata assets
121 : : ) external view override returns (uint256[] memory) {
122 : 3 : uint256[] memory prices = new uint256[](assets.length);
123 : 3 : for (uint256 i = 0; i < assets.length; i++) {
124 : 3 : prices[i] = getAssetPrice(assets[i]);
125 : : }
126 : 2 : return prices;
127 : : }
128 : :
129 : : /// @inheritdoc IAaveOracle
130 : : function getSourceOfAsset(address asset) external view override returns (address) {
131 : 4115 : return address(assetsSources[asset]);
132 : : }
133 : :
134 : : /// @inheritdoc IAaveOracle
135 : : function getFallbackOracle() external view returns (address) {
136 : 3 : return address(_fallbackOracle);
137 : : }
138 : :
139 : : function _onlyAssetListingOrPoolAdmins() internal view {
140 : 664 : IACLManager aclManager = IACLManager(ADDRESSES_PROVIDER.getACLManager());
141 : 664 : require(
142 : : aclManager.isAssetListingAdmin(msg.sender) || aclManager.isPoolAdmin(msg.sender),
143 : : Errors.CALLER_NOT_ASSET_LISTING_OR_POOL_ADMIN
144 : : );
145 : : }
146 : : }
|