Skip to content

Commit 9bca403

Browse files
committed
Merge branch 'feat/188-avalanche-usd-quote' into feat/188-avalanche-market
2 parents 14fe2ba + 9982cdd commit 9bca403

32 files changed

+548
-370
lines changed

contracts/misc/AaveOracle.sol

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,34 @@ import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
1818
contract AaveOracle is IPriceOracleGetter, Ownable {
1919
using SafeERC20 for IERC20;
2020

21-
event WethSet(address indexed weth);
21+
event BaseCurrencySet(address indexed baseCurrency, uint256 baseCurrencyUnit);
2222
event AssetSourceUpdated(address indexed asset, address indexed source);
2323
event FallbackOracleUpdated(address indexed fallbackOracle);
2424

2525
mapping(address => IChainlinkAggregator) private assetsSources;
2626
IPriceOracleGetter private _fallbackOracle;
27-
address public immutable WETH;
27+
address public immutable BASE_CURRENCY;
28+
uint256 public immutable BASE_CURRENCY_UNIT;
2829

2930
/// @notice Constructor
3031
/// @param assets The addresses of the assets
3132
/// @param sources The address of the source of each asset
3233
/// @param fallbackOracle The address of the fallback oracle to use if the data of an
3334
/// aggregator is not consistent
35+
/// @param baseCurrency the base currency used for the price quotes. If USD is used, base currency is 0x0
36+
/// @param baseCurrencyUnit the unit of the base currency
3437
constructor(
3538
address[] memory assets,
3639
address[] memory sources,
3740
address fallbackOracle,
38-
address weth
41+
address baseCurrency,
42+
uint256 baseCurrencyUnit
3943
) public {
4044
_setFallbackOracle(fallbackOracle);
4145
_setAssetsSources(assets, sources);
42-
WETH = weth;
43-
emit WethSet(weth);
46+
BASE_CURRENCY = baseCurrency;
47+
BASE_CURRENCY_UNIT = baseCurrencyUnit;
48+
emit BaseCurrencySet(baseCurrency, baseCurrencyUnit);
4449
}
4550

4651
/// @notice External function called by the Aave governance to set or replace sources of assets
@@ -83,8 +88,8 @@ contract AaveOracle is IPriceOracleGetter, Ownable {
8388
function getAssetPrice(address asset) public view override returns (uint256) {
8489
IChainlinkAggregator source = assetsSources[asset];
8590

86-
if (asset == WETH) {
87-
return 1 ether;
91+
if (asset == BASE_CURRENCY) {
92+
return BASE_CURRENCY_UNIT;
8893
} else if (address(source) == address(0)) {
8994
return _fallbackOracle.getAssetPrice(asset);
9095
} else {

hardhat.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ const buidlerConfig: HardhatUserConfig = {
102102
kovan: getCommonNetworkConfig(eEthereumNetwork.kovan, 42),
103103
ropsten: getCommonNetworkConfig(eEthereumNetwork.ropsten, 3),
104104
main: getCommonNetworkConfig(eEthereumNetwork.main, 1),
105-
tenderlyMain: getCommonNetworkConfig(eEthereumNetwork.tenderlyMain, 3030),
105+
tenderly: getCommonNetworkConfig(eEthereumNetwork.tenderly, 3030),
106106
matic: getCommonNetworkConfig(ePolygonNetwork.matic, 137),
107107
mumbai: getCommonNetworkConfig(ePolygonNetwork.mumbai, 80001),
108108
xdai: getCommonNetworkConfig(eXDaiNetwork.xdai, 100),

helper-hardhat-config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork<string> = {
4646
[eEthereumNetwork.coverage]: 'http://localhost:8555',
4747
[eEthereumNetwork.hardhat]: 'http://localhost:8545',
4848
[eEthereumNetwork.buidlerevm]: 'http://localhost:8545',
49-
[eEthereumNetwork.tenderlyMain]: `https://rpc.tenderly.co/fork/${TENDERLY_FORK_ID}`,
49+
[eEthereumNetwork.tenderly]: `https://rpc.tenderly.co/fork/`,
5050
[ePolygonNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com',
5151
[ePolygonNetwork.matic]: 'https://rpc-mainnet.matic.network',
5252
[eXDaiNetwork.xdai]: 'https://rpc.xdaichain.com/',
@@ -61,7 +61,7 @@ export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork<number> = {
6161
[eEthereumNetwork.coverage]: 65 * GWEI,
6262
[eEthereumNetwork.hardhat]: 65 * GWEI,
6363
[eEthereumNetwork.buidlerevm]: 65 * GWEI,
64-
[eEthereumNetwork.tenderlyMain]: 0.01 * GWEI,
64+
[eEthereumNetwork.tenderly]: 1 * GWEI,
6565
[ePolygonNetwork.mumbai]: 1 * GWEI,
6666
[ePolygonNetwork.matic]: 1 * GWEI,
6767
[eXDaiNetwork.xdai]: 1 * GWEI,
@@ -76,7 +76,7 @@ export const BLOCK_TO_FORK: iParamsPerNetwork<number | undefined> = {
7676
[eEthereumNetwork.coverage]: undefined,
7777
[eEthereumNetwork.hardhat]: undefined,
7878
[eEthereumNetwork.buidlerevm]: undefined,
79-
[eEthereumNetwork.tenderlyMain]: 12406069,
79+
[eEthereumNetwork.tenderly]: undefined,
8080
[ePolygonNetwork.mumbai]: undefined,
8181
[ePolygonNetwork.matic]: undefined,
8282
[eXDaiNetwork.xdai]: undefined,

helpers/configuration.ts

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import {
33
iMultiPoolsAssets,
44
IReserveParams,
55
PoolConfiguration,
6-
ICommonConfiguration,
76
eNetwork,
7+
IBaseConfiguration,
88
} from './types';
99
import { getEthersSignersAddresses, getParamPerPool } from './contracts-helpers';
1010
import AaveConfig from '../markets/aave';
1111
import MaticConfig from '../markets/matic';
1212
import AvalancheConfig from '../markets/avalanche';
1313
import AmmConfig from '../markets/amm';
14+
1415
import { CommonsConfig } from '../markets/aave/commons';
1516
import { DRE, filterMapBy } from './misc-utils';
1617
import { tEthereumAddress } from './types';
@@ -38,7 +39,11 @@ export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => {
3839
case ConfigNames.Commons:
3940
return CommonsConfig;
4041
default:
41-
throw new Error(`Unsupported pool configuration: ${Object.values(ConfigNames)}`);
42+
throw new Error(
43+
`Unsupported pool configuration: ${configName} is not one of the supported configs ${Object.values(
44+
ConfigNames
45+
)}`
46+
);
4247
}
4348
};
4449

@@ -66,7 +71,7 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets<IRes
6671
);
6772

6873
export const getGenesisPoolAdmin = async (
69-
config: ICommonConfiguration
74+
config: IBaseConfiguration
7075
): Promise<tEthereumAddress> => {
7176
const currentNetwork = process.env.FORK ? process.env.FORK : DRE.network.name;
7277
const targetAddress = getParamPerNetwork(config.PoolAdmin, <eNetwork>currentNetwork);
@@ -78,9 +83,7 @@ export const getGenesisPoolAdmin = async (
7883
return addressList[addressIndex];
7984
};
8085

81-
export const getEmergencyAdmin = async (
82-
config: ICommonConfiguration
83-
): Promise<tEthereumAddress> => {
86+
export const getEmergencyAdmin = async (config: IBaseConfiguration): Promise<tEthereumAddress> => {
8487
const currentNetwork = process.env.FORK ? process.env.FORK : DRE.network.name;
8588
const targetAddress = getParamPerNetwork(config.EmergencyAdmin, <eNetwork>currentNetwork);
8689
if (targetAddress) {
@@ -91,19 +94,17 @@ export const getEmergencyAdmin = async (
9194
return addressList[addressIndex];
9295
};
9396

94-
export const getTreasuryAddress = async (
95-
config: ICommonConfiguration
96-
): Promise<tEthereumAddress> => {
97+
export const getTreasuryAddress = async (config: IBaseConfiguration): Promise<tEthereumAddress> => {
9798
const currentNetwork = process.env.FORK ? process.env.FORK : DRE.network.name;
9899
return getParamPerNetwork(config.ReserveFactorTreasuryAddress, <eNetwork>currentNetwork);
99100
};
100101

101102
export const getATokenDomainSeparatorPerNetwork = (
102103
network: eNetwork,
103-
config: ICommonConfiguration
104+
config: IBaseConfiguration
104105
): tEthereumAddress => getParamPerNetwork<tEthereumAddress>(config.ATokenDomainSeparator, network);
105106

106-
export const getWethAddress = async (config: ICommonConfiguration) => {
107+
export const getWethAddress = async (config: IBaseConfiguration) => {
107108
const currentNetwork = process.env.FORK ? process.env.FORK : DRE.network.name;
108109
const wethAddress = getParamPerNetwork(config.WETH, <eNetwork>currentNetwork);
109110
if (wethAddress) {
@@ -116,7 +117,7 @@ export const getWethAddress = async (config: ICommonConfiguration) => {
116117
return weth.address;
117118
};
118119

119-
export const getWrappedNativeTokenAddress = async (config: ICommonConfiguration) => {
120+
export const getWrappedNativeTokenAddress = async (config: IBaseConfiguration) => {
120121
const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name;
121122
const wethAddress = getParamPerNetwork(config.WrappedNativeToken, <eNetwork>currentNetwork);
122123
if (wethAddress) {
@@ -129,7 +130,7 @@ export const getWrappedNativeTokenAddress = async (config: ICommonConfiguration)
129130
return weth.address;
130131
};
131132

132-
export const getLendingRateOracles = (poolConfig: ICommonConfiguration) => {
133+
export const getLendingRateOracles = (poolConfig: IBaseConfiguration) => {
133134
const {
134135
ProtocolGlobalParams: { UsdAddress },
135136
LendingRateOracleRatesCommon,
@@ -141,3 +142,15 @@ export const getLendingRateOracles = (poolConfig: ICommonConfiguration) => {
141142
Object.keys(ReserveAssets[network]).includes(key)
142143
);
143144
};
145+
146+
export const getQuoteCurrency = async (config: IBaseConfiguration) => {
147+
switch (config.OracleQuoteCurrency) {
148+
case 'ETH':
149+
case 'WETH':
150+
return getWethAddress(config);
151+
case 'USD':
152+
return config.ProtocolGlobalParams.UsdAddress;
153+
default:
154+
throw `Quote ${config.OracleQuoteCurrency} currency not set. Add a new case to getQuoteCurrency switch`;
155+
}
156+
};

helpers/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import BigNumber from 'bignumber.js';
2+
import { eEthereumNetwork } from './types';
23

34
// ----------------
45
// MATH
@@ -12,6 +13,7 @@ export const RAY = new BigNumber(10).exponentiatedBy(27).toFixed();
1213
export const HALF_RAY = new BigNumber(RAY).multipliedBy(0.5).toFixed();
1314
export const WAD_RAY_RATIO = Math.pow(10, 9).toString();
1415
export const oneEther = new BigNumber(Math.pow(10, 18));
16+
export const oneUsd = new BigNumber(Math.pow(10, 8));
1517
export const oneRay = new BigNumber(Math.pow(10, 27));
1618
export const MAX_UINT_AMOUNT =
1719
'115792089237316195423570985008687907853269984665640564039457584007913129639935';

helpers/contracts-deployments.ts

Lines changed: 81 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Contract } from 'ethers';
2-
import { DRE } from './misc-utils';
2+
import { DRE, notFalsyOrZeroAddress } from './misc-utils';
33
import {
44
tEthereumAddress,
55
eContractid,
@@ -13,9 +13,8 @@ import {
1313
} from './types';
1414
import { MintableERC20 } from '../types/MintableERC20';
1515
import { MockContract } from 'ethereum-waffle';
16-
import { getReservesConfigByPool } from './configuration';
16+
import { ConfigNames, getReservesConfigByPool, loadPoolConfig } from './configuration';
1717
import { getFirstSigner } from './contracts-getters';
18-
import { ZERO_ADDRESS } from './constants';
1918
import {
2019
AaveProtocolDataProviderFactory,
2120
ATokenFactory,
@@ -57,13 +56,15 @@ import {
5756
insertContractAddressInDb,
5857
deployContract,
5958
verifyContract,
59+
getOptionalParamAddressPerNetwork,
6060
} from './contracts-helpers';
6161
import { StableAndVariableTokensHelperFactory } from '../types/StableAndVariableTokensHelperFactory';
6262
import { MintableDelegationERC20 } from '../types/MintableDelegationERC20';
6363
import { readArtifact as buidlerReadArtifact } from '@nomiclabs/buidler/plugins';
6464
import { HardhatRuntimeEnvironment } from 'hardhat/types';
6565
import { LendingPoolLibraryAddresses } from '../types/LendingPoolFactory';
6666
import { UiPoolDataProvider } from '../types';
67+
import { eNetwork } from './types';
6768

6869
export const deployUiPoolDataProvider = async (
6970
[incentivesController, aaveOracle]: [tEthereumAddress, tEthereumAddress],
@@ -223,7 +224,7 @@ export const deployMockAggregator = async (price: tStringTokenSmallUnits, verify
223224
);
224225

225226
export const deployAaveOracle = async (
226-
args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress, tEthereumAddress],
227+
args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress, tEthereumAddress, string],
227228
verify?: boolean
228229
) =>
229230
withSaveAndVerify(
@@ -351,20 +352,20 @@ export const deployVariableDebtToken = async (
351352
return instance;
352353
};
353354

354-
export const deployGenericStableDebtToken = async () =>
355+
export const deployGenericStableDebtToken = async (verify?: boolean) =>
355356
withSaveAndVerify(
356357
await new StableDebtTokenFactory(await getFirstSigner()).deploy(),
357358
eContractid.StableDebtToken,
358359
[],
359-
false
360+
verify
360361
);
361362

362-
export const deployGenericVariableDebtToken = async () =>
363+
export const deployGenericVariableDebtToken = async (verify?: boolean) =>
363364
withSaveAndVerify(
364365
await new VariableDebtTokenFactory(await getFirstSigner()).deploy(),
365366
eContractid.VariableDebtToken,
366367
[],
367-
false
368+
verify
368369
);
369370

370371
export const deployGenericAToken = async (
@@ -637,3 +638,75 @@ export const deployFlashLiquidationAdapter = async (
637638
args,
638639
verify
639640
);
641+
642+
export const chooseATokenDeployment = (id: eContractid) => {
643+
switch (id) {
644+
case eContractid.AToken:
645+
return deployGenericATokenImpl;
646+
case eContractid.DelegationAwareAToken:
647+
return deployDelegationAwareATokenImpl;
648+
default:
649+
throw Error(`Missing aToken implementation deployment script for: ${id}`);
650+
}
651+
};
652+
653+
export const deployATokenImplementations = async (
654+
pool: ConfigNames,
655+
reservesConfig: { [key: string]: IReserveParams },
656+
verify = false
657+
) => {
658+
const poolConfig = loadPoolConfig(pool);
659+
const network = <eNetwork>DRE.network.name;
660+
661+
// Obtain the different AToken implementations of all reserves inside the Market config
662+
const aTokenImplementations = [
663+
...Object.entries(reservesConfig).reduce<Set<eContractid>>((acc, [, entry]) => {
664+
acc.add(entry.aTokenImpl);
665+
return acc;
666+
}, new Set<eContractid>()),
667+
];
668+
669+
console.log(aTokenImplementations);
670+
671+
for (let x = 0; x < aTokenImplementations.length; x++) {
672+
const aTokenAddress = getOptionalParamAddressPerNetwork(
673+
poolConfig[aTokenImplementations[x].toString()],
674+
network
675+
);
676+
if (!notFalsyOrZeroAddress(aTokenAddress)) {
677+
const deployImplementationMethod = chooseATokenDeployment(aTokenImplementations[x]);
678+
console.log(`Deploying implementation`, aTokenImplementations[x]);
679+
await deployImplementationMethod(verify);
680+
}
681+
}
682+
683+
// Debt tokens, for now all Market configs follows same implementations
684+
const genericStableDebtTokenAddress = getOptionalParamAddressPerNetwork(
685+
poolConfig.StableDebtTokenImplementation,
686+
network
687+
);
688+
const geneticVariableDebtTokenAddress = getOptionalParamAddressPerNetwork(
689+
poolConfig.VariableDebtTokenImplementation,
690+
network
691+
);
692+
693+
if (!notFalsyOrZeroAddress(genericStableDebtTokenAddress)) {
694+
await deployGenericStableDebtToken(verify);
695+
}
696+
if (!notFalsyOrZeroAddress(geneticVariableDebtTokenAddress)) {
697+
await deployGenericVariableDebtToken(verify);
698+
}
699+
};
700+
701+
export const deployRateStrategy = async (
702+
strategyName: string,
703+
args: [tEthereumAddress, string, string, string, string, string, string],
704+
verify: boolean
705+
): Promise<tEthereumAddress> => {
706+
switch (strategyName) {
707+
default:
708+
return await (
709+
await deployDefaultReserveInterestRateStrategy(args, verify)
710+
).address;
711+
}
712+
};

0 commit comments

Comments
 (0)