mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
feat: Added AaveOracleV2 with custom quote asset. Support AaveOracleV2 in deployment scripts.
This commit is contained in:
parent
0b109da9c6
commit
7d51b97b27
125
contracts/misc/AaveOracleV2.sol
Normal file
125
contracts/misc/AaveOracleV2.sol
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
// SPDX-License-Identifier: agpl-3.0
|
||||||
|
pragma solidity 0.6.12;
|
||||||
|
|
||||||
|
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
|
||||||
|
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||||
|
|
||||||
|
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
|
||||||
|
import {IChainlinkAggregator} from '../interfaces/IChainlinkAggregator.sol';
|
||||||
|
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
|
||||||
|
|
||||||
|
/// @title AaveOracleV2
|
||||||
|
/// @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 AaveOracleV2 is IPriceOracleGetter, Ownable {
|
||||||
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
|
event QuoteCurrencySet(address indexed quoteCurrency, uint256 quoteUnit);
|
||||||
|
event AssetSourceUpdated(address indexed asset, address indexed source);
|
||||||
|
event FallbackOracleUpdated(address indexed fallbackOracle);
|
||||||
|
|
||||||
|
mapping(address => IChainlinkAggregator) private assetsSources;
|
||||||
|
IPriceOracleGetter private _fallbackOracle;
|
||||||
|
address public immutable QUOTE_CURRENCY;
|
||||||
|
uint256 public immutable QUOTE_CURRENCY_UNIT;
|
||||||
|
|
||||||
|
/// @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,
|
||||||
|
address quoteCurrency,
|
||||||
|
uint256 quoteCurrencyUnits
|
||||||
|
) public {
|
||||||
|
_setFallbackOracle(fallbackOracle);
|
||||||
|
_setAssetsSources(assets, sources);
|
||||||
|
QUOTE_CURRENCY = quoteCurrency;
|
||||||
|
QUOTE_CURRENCY_UNIT = quoteCurrencyUnits;
|
||||||
|
emit QuoteCurrencySet(quoteCurrency, quoteCurrencyUnits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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
|
||||||
|
{
|
||||||
|
_setAssetsSources(assets, sources);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Sets the fallbackOracle
|
||||||
|
/// - Callable only by the Aave governance
|
||||||
|
/// @param fallbackOracle The address of the fallbackOracle
|
||||||
|
function setFallbackOracle(address fallbackOracle) external onlyOwner {
|
||||||
|
_setFallbackOracle(fallbackOracle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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 _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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Internal function to set the fallbackOracle
|
||||||
|
/// @param fallbackOracle The address of the fallbackOracle
|
||||||
|
function _setFallbackOracle(address fallbackOracle) internal {
|
||||||
|
_fallbackOracle = IPriceOracleGetter(fallbackOracle);
|
||||||
|
emit FallbackOracleUpdated(fallbackOracle);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Gets an asset price by address
|
||||||
|
/// @param asset The asset address
|
||||||
|
function getAssetPrice(address asset) public view override returns (uint256) {
|
||||||
|
IChainlinkAggregator source = assetsSources[asset];
|
||||||
|
|
||||||
|
if (asset == QUOTE_CURRENCY) {
|
||||||
|
return QUOTE_CURRENCY_UNIT;
|
||||||
|
} else if (address(source) == address(0)) {
|
||||||
|
return _fallbackOracle.getAssetPrice(asset);
|
||||||
|
} else {
|
||||||
|
int256 price = IChainlinkAggregator(source).latestAnswer();
|
||||||
|
if (price > 0) {
|
||||||
|
return uint256(price);
|
||||||
|
} else {
|
||||||
|
return _fallbackOracle.getAssetPrice(asset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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]);
|
||||||
|
}
|
||||||
|
return prices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,6 +52,7 @@ import {
|
||||||
RewardsTokenFactory,
|
RewardsTokenFactory,
|
||||||
RewardsATokenMockFactory,
|
RewardsATokenMockFactory,
|
||||||
CurveRewardsAwareATokenFactory,
|
CurveRewardsAwareATokenFactory,
|
||||||
|
AaveOracleV2Factory,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {
|
import {
|
||||||
withSaveAndVerify,
|
withSaveAndVerify,
|
||||||
|
@ -225,7 +226,7 @@ export const deployMockAggregator = async (price: tStringTokenSmallUnits, verify
|
||||||
);
|
);
|
||||||
|
|
||||||
export const deployAaveOracle = async (
|
export const deployAaveOracle = async (
|
||||||
args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress, tEthereumAddress, string],
|
args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress, tEthereumAddress],
|
||||||
verify?: boolean
|
verify?: boolean
|
||||||
) =>
|
) =>
|
||||||
withSaveAndVerify(
|
withSaveAndVerify(
|
||||||
|
@ -235,6 +236,17 @@ export const deployAaveOracle = async (
|
||||||
verify
|
verify
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const deployAaveOracleV2 = async (
|
||||||
|
args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress, tEthereumAddress, string],
|
||||||
|
verify?: boolean
|
||||||
|
) =>
|
||||||
|
withSaveAndVerify(
|
||||||
|
await new AaveOracleV2Factory(await getFirstSigner()).deploy(...args),
|
||||||
|
eContractid.AaveOracle,
|
||||||
|
args,
|
||||||
|
verify
|
||||||
|
);
|
||||||
|
|
||||||
export const deployLendingPoolCollateralManager = async (verify?: boolean) => {
|
export const deployLendingPoolCollateralManager = async (verify?: boolean) => {
|
||||||
const collateralManagerImpl = await new LendingPoolCollateralManagerFactory(
|
const collateralManagerImpl = await new LendingPoolCollateralManagerFactory(
|
||||||
await getFirstSigner()
|
await getFirstSigner()
|
||||||
|
|
|
@ -143,7 +143,6 @@ export const initReservesByHelper = async (
|
||||||
|
|
||||||
console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`);
|
console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`);
|
||||||
for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) {
|
for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) {
|
||||||
console.log(chunkedInitInputParams[chunkIndex]);
|
|
||||||
const tx3 = await waitForTx(
|
const tx3 = await waitForTx(
|
||||||
await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex])
|
await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex])
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { task } from 'hardhat/config';
|
import { task } from 'hardhat/config';
|
||||||
import {
|
import {
|
||||||
deployPriceOracle,
|
deployPriceOracle,
|
||||||
deployAaveOracle,
|
deployAaveOracleV2,
|
||||||
deployLendingRateOracle,
|
deployLendingRateOracle,
|
||||||
} from '../../helpers/contracts-deployments';
|
} from '../../helpers/contracts-deployments';
|
||||||
import {
|
import {
|
||||||
|
@ -64,7 +64,7 @@ task('dev:deploy-oracles', 'Deploy oracles for dev environment')
|
||||||
OracleQuoteCurrency
|
OracleQuoteCurrency
|
||||||
);
|
);
|
||||||
|
|
||||||
await deployAaveOracle(
|
await deployAaveOracleV2(
|
||||||
[
|
[
|
||||||
tokens,
|
tokens,
|
||||||
aggregators,
|
aggregators,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { task } from 'hardhat/config';
|
import { task } from 'hardhat/config';
|
||||||
import { getParamPerNetwork } from '../../helpers/contracts-helpers';
|
import { getParamPerNetwork } from '../../helpers/contracts-helpers';
|
||||||
import { deployAaveOracle, deployLendingRateOracle } from '../../helpers/contracts-deployments';
|
import { deployAaveOracleV2, deployLendingRateOracle } from '../../helpers/contracts-deployments';
|
||||||
import { setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers';
|
import { setInitialMarketRatesInRatesOracleByHelper } from '../../helpers/oracles-helpers';
|
||||||
import { ICommonConfiguration, eNetwork, SymbolMap } from '../../helpers/types';
|
import { ICommonConfiguration, eNetwork, SymbolMap } from '../../helpers/types';
|
||||||
import { waitForTx, notFalsyOrZeroAddress } from '../../helpers/misc-utils';
|
import { waitForTx, notFalsyOrZeroAddress } from '../../helpers/misc-utils';
|
||||||
|
@ -59,7 +59,7 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment')
|
||||||
if (notFalsyOrZeroAddress(aaveOracleAddress)) {
|
if (notFalsyOrZeroAddress(aaveOracleAddress)) {
|
||||||
aaveOracle = await await getAaveOracle(aaveOracleAddress);
|
aaveOracle = await await getAaveOracle(aaveOracleAddress);
|
||||||
} else {
|
} else {
|
||||||
aaveOracle = await deployAaveOracle(
|
aaveOracle = await deployAaveOracleV2(
|
||||||
[
|
[
|
||||||
tokens,
|
tokens,
|
||||||
aggregators,
|
aggregators,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
deployLendingPoolConfigurator,
|
deployLendingPoolConfigurator,
|
||||||
deployLendingPool,
|
deployLendingPool,
|
||||||
deployPriceOracle,
|
deployPriceOracle,
|
||||||
deployAaveOracle,
|
deployAaveOracleV2,
|
||||||
deployLendingPoolCollateralManager,
|
deployLendingPoolCollateralManager,
|
||||||
deployMockFlashLoanReceiver,
|
deployMockFlashLoanReceiver,
|
||||||
deployWalletBalancerProvider,
|
deployWalletBalancerProvider,
|
||||||
|
@ -200,6 +200,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
STAKE: mockTokens.STAKE.address,
|
STAKE: mockTokens.STAKE.address,
|
||||||
xSUSHI: mockTokens.xSUSHI.address,
|
xSUSHI: mockTokens.xSUSHI.address,
|
||||||
REW: mockTokens.REW.address,
|
REW: mockTokens.REW.address,
|
||||||
|
'a3CRV-gauge': ZERO_ADDRESS,
|
||||||
|
'saCRV-gauge': ZERO_ADDRESS,
|
||||||
},
|
},
|
||||||
fallbackOracle
|
fallbackOracle
|
||||||
);
|
);
|
||||||
|
@ -226,7 +228,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
config.OracleQuoteCurrency
|
config.OracleQuoteCurrency
|
||||||
);
|
);
|
||||||
|
|
||||||
await deployAaveOracle([
|
await deployAaveOracleV2([
|
||||||
tokens,
|
tokens,
|
||||||
aggregators,
|
aggregators,
|
||||||
fallbackOracle.address,
|
fallbackOracle.address,
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
deployLendingPoolConfigurator,
|
deployLendingPoolConfigurator,
|
||||||
deployLendingPool,
|
deployLendingPool,
|
||||||
deployPriceOracle,
|
deployPriceOracle,
|
||||||
deployAaveOracle,
|
deployAaveOracleV2,
|
||||||
deployLendingPoolCollateralManager,
|
deployLendingPoolCollateralManager,
|
||||||
deployMockFlashLoanReceiver,
|
deployMockFlashLoanReceiver,
|
||||||
deployWalletBalancerProvider,
|
deployWalletBalancerProvider,
|
||||||
|
@ -199,6 +199,10 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
WMATIC: mockTokens.WMATIC.address,
|
WMATIC: mockTokens.WMATIC.address,
|
||||||
USD: USD_ADDRESS,
|
USD: USD_ADDRESS,
|
||||||
STAKE: mockTokens.STAKE.address,
|
STAKE: mockTokens.STAKE.address,
|
||||||
|
'a3CRV-gauge': ZERO_ADDRESS,
|
||||||
|
'saCRV-gauge': ZERO_ADDRESS,
|
||||||
|
xSUSHI: ZERO_ADDRESS,
|
||||||
|
REW: ZERO_ADDRESS,
|
||||||
},
|
},
|
||||||
fallbackOracle
|
fallbackOracle
|
||||||
);
|
);
|
||||||
|
@ -226,7 +230,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
config.OracleQuoteCurrency
|
config.OracleQuoteCurrency
|
||||||
);
|
);
|
||||||
|
|
||||||
await deployAaveOracle([
|
await deployAaveOracleV2([
|
||||||
tokens,
|
tokens,
|
||||||
aggregators,
|
aggregators,
|
||||||
fallbackOracle.address,
|
fallbackOracle.address,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user