Merge branch 'master' into 178-add-uniswap-adapters

This commit is contained in:
The3D 2020-12-02 10:14:03 +01:00
commit 2e23281cdc
19 changed files with 658 additions and 322 deletions

View File

@ -0,0 +1,28 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
interface ICreditDelegationToken {
event BorrowAllowanceDelegated(
address indexed fromUser,
address indexed toUser,
address asset,
uint256 amount
);
/**
* @dev delegates borrowing power to a user on the specific debt token
* @param delegatee the address receiving the delegated borrowing power
* @param amount the maximum amount being delegated. Delegation will still
* respect the liquidation constraints (even if delegated, a delegatee cannot
* force a delegator HF to go below 1)
**/
function approveDelegation(address delegatee, uint256 amount) external;
/**
* @dev returns the borrow allowance of the user
* @param fromUser The user to giving allowance
* @param toUser The user to give allowance to
* @return the current allowance of toUser
**/
function borrowAllowance(address fromUser, address toUser) external view returns (uint256);
}

View File

@ -2,6 +2,7 @@
pragma solidity 0.6.12;
import {ILendingPool} from '../../../interfaces/ILendingPool.sol';
import {ICreditDelegationToken} from '../../../interfaces/ICreditDelegationToken.sol';
import {
VersionedInitializable
} from '../../libraries/aave-upgradeability/VersionedInitializable.sol';
@ -14,14 +15,11 @@ import {Errors} from '../../libraries/helpers/Errors.sol';
* @author Aave
*/
abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
event BorrowAllowanceDelegated(
address indexed fromUser,
address indexed toUser,
address asset,
uint256 amount
);
abstract contract DebtTokenBase is
IncentivizedERC20,
VersionedInitializable,
ICreditDelegationToken
{
address public immutable UNDERLYING_ASSET_ADDRESS;
ILendingPool public immutable POOL;
@ -73,7 +71,7 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
* respect the liquidation constraints (even if delegated, a delegatee cannot
* force a delegator HF to go below 1)
**/
function approveDelegation(address delegatee, uint256 amount) external {
function approveDelegation(address delegatee, uint256 amount) external override {
_borrowAllowances[_msgSender()][delegatee] = amount;
emit BorrowAllowanceDelegated(_msgSender(), delegatee, UNDERLYING_ASSET_ADDRESS, amount);
}
@ -84,7 +82,12 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
* @param toUser The user to give allowance to
* @return the current allowance of toUser
**/
function borrowAllowance(address fromUser, address toUser) external view returns (uint256) {
function borrowAllowance(address fromUser, address toUser)
external
view
override
returns (uint256)
{
return _borrowAllowances[fromUser][toUser];
}

View File

@ -1,9 +1,6 @@
import path from 'path';
import fs from 'fs';
import { HardhatUserConfig } from 'hardhat/types';
require('dotenv').config();
// @ts-ignore
import { accounts } from './test-wallets.js';
import { eEthereumNetwork } from './helpers/types';
@ -65,7 +62,7 @@ const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number
const mainnetFork = MAINNET_FORK
? {
blockNumber: 11268220,
blockNumber: 11361132,
url: ALCHEMY_KEY
? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}`
: `https://main.infura.io/v3/${INFURA_KEY}`,

View File

@ -7,7 +7,7 @@ import {
getStableAndVariableTokensHelper,
} from './contracts-getters';
import { rawInsertContractAddressInDb } from './contracts-helpers';
import { BigNumberish } from 'ethers';
import { BigNumber, BigNumberish } from 'ethers';
import {
deployDefaultReserveInterestRateStrategy,
deployDelegationAwareAToken,
@ -35,8 +35,8 @@ export const initReservesByHelper = async (
treasuryAddress: tEthereumAddress,
incentivesController: tEthereumAddress,
verify: boolean
) => {
): Promise<BigNumber> => {
let gasUsage = BigNumber.from('0');
const stableAndVariableDeployer = await getStableAndVariableTokensHelper();
const atokenAndRatesDeployer = await getATokensAndRatesHelper();
@ -47,8 +47,8 @@ export const initReservesByHelper = async (
await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address));
// CHUNK CONFIGURATION
const tokensChunks = 4;
const initChunks = 6;
const tokensChunks = 2;
const initChunks = 4;
// Deploy tokens and rates that uses common aToken in chunks
const reservesChunks = chunk(
@ -123,17 +123,13 @@ export const initReservesByHelper = async (
// Deploy stable and variable deployers and save implementations
const tx1 = await waitForTx(
await stableAndVariableDeployer.initDeployment(
tokens,
symbols,
incentivesController
)
await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController)
);
tx1.events?.forEach((event, index) => {
rawInsertContractAddressInDb(`stableDebt${symbols[index]}`, event?.args?.stableToken);
rawInsertContractAddressInDb(`variableDebt${symbols[index]}`, event?.args?.variableToken);
});
// Deploy atokens and rate strategies and save implementations
const tx2 = await waitForTx(
await atokenAndRatesDeployer.initDeployment(
@ -150,6 +146,10 @@ export const initReservesByHelper = async (
});
console.log(` - Deployed aToken, DebtTokens and Strategy for: ${symbols.join(', ')} `);
console.log(' * gasUsed: debtTokens batch', tx1.gasUsed.toString());
console.log(' * gasUsed: aTokens and Strategy batch', tx2.gasUsed.toString());
gasUsage = gasUsage.add(tx1.gasUsed).add(tx2.gasUsed);
const stableTokens: string[] = tx1.events?.map((e) => e.args?.stableToken) || [];
const variableTokens: string[] = tx1.events?.map((e) => e.args?.variableToken) || [];
const aTokens: string[] = tx2.events?.map((e) => e.args?.aToken) || [];
@ -252,11 +252,15 @@ export const initReservesByHelper = async (
chunkedDecimals[chunkIndex]
)
);
console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`);
console.log(' * gasUsed', tx3.gasUsed.toString());
gasUsage = gasUsage.add(tx3.gasUsed);
}
// Set deployer back as admin
await waitForTx(await addressProvider.setPoolAdmin(admin));
return gasUsage;
};
export const getPairsTokenAggregator = (
@ -304,7 +308,13 @@ export const configureReservesByHelper = async (
for (const [
assetSymbol,
{ baseLTVAsCollateral, liquidationBonus, liquidationThreshold, reserveFactor, stableBorrowRateEnabled },
{
baseLTVAsCollateral,
liquidationBonus,
liquidationThreshold,
reserveFactor,
stableBorrowRateEnabled,
},
] of Object.entries(reservesParams) as [string, IReserveParams][]) {
if (baseLTVAsCollateral === '-1') continue;

View File

@ -354,6 +354,7 @@ export interface ICommonConfiguration {
ProtocolGlobalParams: IProtocolGlobalConfig;
Mocks: IMocksConfig;
ProviderRegistry: iParamsPerNetwork<tEthereumAddress | undefined>;
ProviderRegistryOwner: iParamsPerNetwork<tEthereumAddress | undefined>;
LendingRateOracleRatesCommon: iMultiPoolsAssets<IMarketRates>;
LendingRateOracle: iParamsPerNetwork<tEthereumAddress>;
TokenDistributor: iParamsPerNetwork<tEthereumAddress>;

View File

@ -137,13 +137,22 @@ export const CommonsConfig: ICommonConfiguration = {
},
EmergencyAdminIndex: 1,
ProviderRegistry: {
[eEthereumNetwork.kovan]: '',
[eEthereumNetwork.kovan]: '0x1E40B561EC587036f9789aF83236f057D1ed2A90',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '',
[eEthereumNetwork.main]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413',
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.tenderlyMain]: '',
[eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413',
},
ProviderRegistryOwner: {
[eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f',
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f',
},
LendingRateOracle: {
[eEthereumNetwork.coverage]: '',
@ -151,8 +160,8 @@ export const CommonsConfig: ICommonConfiguration = {
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a',
[eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b',
[eEthereumNetwork.main]: ZERO_ADDRESS,
[eEthereumNetwork.tenderlyMain]: ZERO_ADDRESS,
[eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D',
[eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D',
},
TokenDistributor: {
[eEthereumNetwork.coverage]: '',
@ -169,8 +178,8 @@ export const CommonsConfig: ICommonConfiguration = {
[eEthereumNetwork.buidlerevm]: '',
[EthereumNetwork.kovan]: '0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1',
[EthereumNetwork.ropsten]: ZERO_ADDRESS,
[EthereumNetwork.main]: ZERO_ADDRESS,
[EthereumNetwork.tenderlyMain]: ZERO_ADDRESS,
[EthereumNetwork.main]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9',
[EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9',
},
FallbackOracle: {
[eEthereumNetwork.coverage]: '',
@ -307,7 +316,7 @@ export const CommonsConfig: ICommonConfiguration = {
},
ReserveFactorTreasuryAddress: {
[eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.hardhat]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.hardhat]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.buidlerevm]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.kovan]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',

View File

@ -3,14 +3,15 @@ import { IAaveConfiguration, EthereumNetwork, eEthereumNetwork } from '../../hel
import { CommonsConfig } from './commons';
import {
stablecoinStrategyBUSD,
stablecoinStrategyDAI,
stablecoinStrategySUSD,
stablecoinStrategyTUSD,
stablecoinStrategyUSDC,
stablecoinStrategyUSDT,
strategyBUSD,
strategyDAI,
strategySUSD,
strategyTUSD,
strategyUSDC,
strategyUSDT,
strategyAAVE,
strategyBase,
strategyBAT,
strategyZRX,
strategyKNC,
strategyLINK,
strategyMANA,
@ -33,9 +34,9 @@ export const AaveConfig: IAaveConfiguration = {
ProviderId: 1,
ReservesConfig: {
AAVE: strategyAAVE,
BAT: strategyBase,
BUSD: stablecoinStrategyBUSD,
DAI: stablecoinStrategyDAI,
BAT: strategyBAT,
BUSD: strategyBUSD,
DAI: strategyDAI,
ENJ: strategyREN,
KNC: strategyKNC,
LINK: strategyLINK,
@ -43,15 +44,15 @@ export const AaveConfig: IAaveConfiguration = {
MKR: strategyMKR,
REN: strategyREN,
SNX: strategySNX,
SUSD: stablecoinStrategySUSD,
TUSD: stablecoinStrategyTUSD,
SUSD: strategySUSD,
TUSD: strategyTUSD,
UNI: strategyUNI,
USDC: stablecoinStrategyUSDC,
USDT: stablecoinStrategyUSDT,
USDC: strategyUSDC,
USDT: strategyUSDT,
WBTC: strategyWBTC,
WETH: strategyWETH,
YFI: strategyYFI,
ZRX: strategyBase,
ZRX: strategyZRX,
},
ReserveAssets: {
[eEthereumNetwork.buidlerevm]: {},

View File

@ -2,9 +2,213 @@ import BigNumber from 'bignumber.js';
import { oneRay } from '../../helpers/constants';
import { eContractid, IReserveParams } from '../../helpers/types';
export const strategyBase: IReserveParams = {
export const strategyBUSD: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
baseLTVAsCollateral: '0',
liquidationThreshold: '0',
liquidationBonus: '0',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyDAI: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategySUSD: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
baseLTVAsCollateral: '0',
liquidationThreshold: '0',
liquidationBonus: '0',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyTUSD: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyUSDC: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyUSDT: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyAAVE: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: '0',
variableRateSlope2: '0',
stableRateSlope1: '0',
stableRateSlope2: '0',
baseLTVAsCollateral: '5000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
borrowingEnabled: false,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '0'
};
export const strategyBAT: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyENJ: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '5500',
liquidationThreshold: '6000',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyWETH: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '8000',
liquidationThreshold: '8250',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyKNC: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyLINK: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyMANA: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
@ -16,210 +220,124 @@ export const strategyBase: IReserveParams = {
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
reserveFactor: '3500'
};
export const stablecoinStrategyBase: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
export const strategyMKR: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1.5).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.06).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(1.5).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
reserveFactor: '2000'
};
export const stablecoinStrategyCentralized: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
export const strategyREN: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.06).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '5500',
liquidationThreshold: '6000',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyGovernanceTokens: IReserveParams = {
...strategyBase,
baseLTVAsCollateral: '4000',
liquidationBonus: '11500',
};
export const stablecoinStrategyBUSD: IReserveParams = {
...stablecoinStrategyCentralized,
reserveDecimals: '18',
baseLTVAsCollateral: '-1',
liquidationThreshold: '0',
liquidationBonus: '0',
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategySNX: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.12).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
baseLTVAsCollateral: '1500',
liquidationThreshold: '4000',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
stableRateSlope1: new BigNumber(0.14).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '3500'
};
export const strategyAAVE: IReserveParams = {
...strategyBase,
baseLTVAsCollateral: '5000',
export const strategyUNI: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: '0',
variableRateSlope2: '0',
stableRateSlope1: '0',
stableRateSlope2: '0',
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
borrowingEnabled: false,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
};
export const stablecoinStrategyDAI: IReserveParams = {
...stablecoinStrategyBase,
};
export const strategyENJ: IReserveParams = {
...strategyBase,
baseLTVAsCollateral: '5500',
stableBorrowRateEnabled: false,
};
export const strategyKNC: IReserveParams = {
...strategyBase,
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
};
export const strategyLINK: IReserveParams = {
...strategyBase,
baseLTVAsCollateral: '6500',
liquidationThreshold: '7000',
};
export const strategyMANA: IReserveParams = {
...strategyBase,
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
};
export const strategyMKR: IReserveParams = {
...strategyBase,
baseLTVAsCollateral: '3500',
};
export const strategyREN: IReserveParams = {
...strategyBase,
baseLTVAsCollateral: '5000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
};
export const stablecoinStrategySUSD: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.14).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '-1',
liquidationThreshold: '0',
liquidationBonus: '0',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategySNX: IReserveParams = {
...strategyBase,
baseLTVAsCollateral: '1500',
liquidationThreshold: '4000',
baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.12).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableBorrowRateEnabled: false,
};
export const stablecoinStrategyTUSD: IReserveParams = {
...stablecoinStrategyCentralized,
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1.5).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.14).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
};
export const strategyUNI: IReserveParams = {
...strategyGovernanceTokens,
stableBorrowRateEnabled: false,
aTokenImpl: eContractid.DelegationAwareAToken,
};
export const stablecoinStrategyUSDC: IReserveParams = {
...stablecoinStrategyBase,
variableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
reserveDecimals: '6',
};
export const stablecoinStrategyUSDT: IReserveParams = {
...stablecoinStrategyBase,
baseLTVAsCollateral: '-1',
liquidationThreshold: '7000',
liquidationBonus: '0',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '6',
reserveFactor: '2000'
};
export const strategyWBTC: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11500',
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '8',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
reserveFactor: '2000'
};
export const strategyWETH: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
export const strategyYFI: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '4000',
liquidationThreshold: '5500',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
reserveFactor: '2000'
};
export const strategyYFI: IReserveParams = {
...strategyGovernanceTokens,
};
export const strategyZRX: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};

View File

@ -35,7 +35,7 @@
"aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify",
"aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet",
"aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet",
"aave:main:full:migration": "npm run hardhat:main -- aave:mainnet --verify",
"aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify",
"dev:prettier": "prettier --write .",
"ci:test": "npm run compile && npm run test",
"ci:clean": "rm -rf ./artifacts ./cache ./types",
@ -45,12 +45,16 @@
"dev:deployUIProvider": "npm run hardhat:kovan deploy-UiPoolDataProvider",
"dev:deployUniswapRepayAdapter": "npm run hardhat:kovan deploy-UniswapRepayAdapter",
"dev:UniswapLiquiditySwapAdapter": "npm run hardhat:kovan deploy-UniswapLiquiditySwapAdapter",
"main:deployUniswapRepayAdapter": "npm run hardhat:main deploy-UniswapRepayAdapter",
"main:UniswapLiquiditySwapAdapter": "npm run hardhat:main deploy-UniswapLiquiditySwapAdapter",
"kovan:verify": "npm run hardhat:kovan verify:general -- --all --pool Aave",
"ropsten:verify": "npm run hardhat:ropsten verify:general -- --all --pool Aave",
"mainnet:verify": "npm run hardhat:main verify:general -- --all --pool Aave",
"kovan:verify:tokens": "npm run hardhat:kovan verify:tokens -- --pool Aave",
"ropsten:verify:tokens": "npm run hardhat:ropsten verify:tokens -- --pool Aave",
"mainnet:verify:tokens": "npm run hardhat:main verify:tokens -- --pool Aave"
"mainnet:verify:tokens": "npm run hardhat:main verify:tokens -- --pool Aave",
"print-config:fork:mainnet": "MAINNET_FORK=true hardhat print-config:fork",
"print-config:kovan": "hardhat --network kovan print-config --pool Aave --data-provider 0xA1901785c29cBd48bfA74e46b67C736b26054fa4"
},
"devDependencies": {
"@nomiclabs/buidler": "^1.4.7",

View File

@ -0,0 +1,11 @@
import { task } from 'hardhat/config';
import { deployLendingPoolAddressesProviderRegistry } from '../../helpers/contracts-deployments';
task('full:deploy-address-provider-registry', 'Deploy address provider registry')
.addFlag('verify', 'Verify contracts at Etherscan')
.setAction(async ({ verify }, DRE) => {
await DRE.run('set-DRE');
const contract = await deployLendingPoolAddressesProviderRegistry(verify);
console.log('Registry Address:', contract.address);
});

View File

@ -12,7 +12,13 @@ import {
getEmergencyAdmin,
} from '../../helpers/configuration';
import { eEthereumNetwork } from '../../helpers/types';
import { getLendingPoolAddressesProviderRegistry } from '../../helpers/contracts-getters';
import {
getFirstSigner,
getLendingPoolAddressesProviderRegistry,
} from '../../helpers/contracts-getters';
import { isAddress } from 'ethers/lib/utils';
import { isZeroAddress } from 'ethereumjs-util';
import { Signer } from 'ethers';
task(
'full:deploy-address-provider',
@ -22,30 +28,70 @@ task(
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
.setAction(async ({ verify, pool }, DRE) => {
await DRE.run('set-DRE');
let signer: Signer;
const network = <eEthereumNetwork>DRE.network.name;
const poolConfig = loadPoolConfig(pool);
const { ProviderId, MarketId } = poolConfig;
const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network);
// Deploy address provider and set genesis manager
const providerRegistryOwner = getParamPerNetwork(poolConfig.ProviderRegistryOwner, network);
if (
!providerRegistryAddress ||
!isAddress(providerRegistryAddress) ||
isZeroAddress(providerRegistryAddress)
) {
throw Error('config.ProviderRegistry is missing or is not an address.');
}
if (
!providerRegistryOwner ||
!isAddress(providerRegistryOwner) ||
isZeroAddress(providerRegistryOwner)
) {
throw Error('config.ProviderRegistryOwner is missing or is not an address.');
}
// Checks if deployer address is registry owner
if (process.env.MAINNET_FORK === 'true') {
await DRE.network.provider.request({
method: 'hardhat_impersonateAccount',
params: [providerRegistryOwner],
});
signer = DRE.ethers.provider.getSigner(providerRegistryOwner);
} else {
signer = await getFirstSigner();
const deployerAddress = await signer.getAddress();
if (providerRegistryOwner !== (await signer.getAddress())) {
throw Error(
`Current signer is not provider registry owner. \nCurrent deployer address: ${deployerAddress} \nExpected address: ${poolConfig.ProviderRegistryOwner}`
);
}
}
// 1. Address Provider Registry instance
const addressesProviderRegistry = (
await getLendingPoolAddressesProviderRegistry(providerRegistryAddress)
).connect(signer);
console.log('Registry Address', addressesProviderRegistry.address);
// 2. Deploy address provider and set genesis manager
const addressesProvider = await deployLendingPoolAddressesProvider(MarketId, verify);
await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig)));
await waitForTx(await addressesProvider.setEmergencyAdmin(await getEmergencyAdmin(poolConfig)));
console.log('Pool Admin', await addressesProvider.getPoolAdmin());
console.log('Emergency Admin', await addressesProvider.getEmergencyAdmin());
// If no provider registry is set, deploy lending pool address provider registry and register the address provider
const addressesProviderRegistry = notFalsyOrZeroAddress(providerRegistryAddress)
? await getLendingPoolAddressesProviderRegistry(providerRegistryAddress)
: await deployLendingPoolAddressesProviderRegistry(verify);
// 3. Set the provider at the Registry
await waitForTx(
await addressesProviderRegistry.registerAddressesProvider(
addressesProvider.address,
ProviderId
)
);
// 4. Set pool admins
await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig)));
await waitForTx(await addressesProvider.setEmergencyAdmin(await getEmergencyAdmin(poolConfig)));
console.log('Pool Admin', await addressesProvider.getPoolAdmin());
console.log('Emergency Admin', await addressesProvider.getEmergencyAdmin());
});

View File

@ -0,0 +1,77 @@
import { task } from 'hardhat/config';
import { ConfigNames, loadPoolConfig } from '../../helpers/configuration';
import {
getAaveProtocolDataProvider,
getLendingPoolAddressesProvider,
getLendingPoolAddressesProviderRegistry,
} from '../../helpers/contracts-getters';
import { getParamPerNetwork } from '../../helpers/contracts-helpers';
import { DRE } from '../../helpers/misc-utils';
import { eEthereumNetwork } from '../../helpers/types';
task('print-config', 'Inits the DRE, to have access to all the plugins')
.addParam('dataProvider', 'Address of AaveProtocolDataProvider')
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
.setAction(async ({ pool, dataProvider }, localBRE) => {
await localBRE.run('set-DRE');
const network =
process.env.MAINNET_FORK === 'true'
? eEthereumNetwork.main
: (localBRE.network.name as eEthereumNetwork);
const poolConfig = loadPoolConfig(pool);
const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network);
const providerRegistry = await getLendingPoolAddressesProviderRegistry(providerRegistryAddress);
const providers = await providerRegistry.getAddressesProvidersList();
const addressesProvider = await getLendingPoolAddressesProvider(providers[0]); // Checks first provider
console.log('Addresses Providers', providers.join(', '));
console.log('Market Id: ', await addressesProvider.getMarketId());
console.log('LendingPool Proxy:', await addressesProvider.getLendingPool());
console.log(
'Lending Pool Collateral Manager',
await addressesProvider.getLendingPoolCollateralManager()
);
console.log(
'Lending Pool Configurator proxy',
await addressesProvider.getLendingPoolConfigurator()
);
console.log('Pool admin', await addressesProvider.getPoolAdmin());
console.log('Emergency admin', await addressesProvider.getEmergencyAdmin());
console.log('Price Oracle', await addressesProvider.getPriceOracle());
console.log('Lending Rate Oracle', await addressesProvider.getLendingRateOracle());
console.log('Lending Pool Data Provider', dataProvider);
const protocolDataProvider = await getAaveProtocolDataProvider(dataProvider);
const fields = [
'decimals',
'ltv',
'liquidationThreshold',
'liquidationBonus',
'reserveFactor',
'usageAsCollateralEnabled',
'borrowingEnabled',
'stableBorrowRateEnabled',
'isActive',
'isFrozen',
];
const tokensFields = ['aToken', 'stableDebtToken', 'variableDebtToken'];
for (const [symbol, address] of Object.entries(
getParamPerNetwork(poolConfig.ReserveAssets, network)
)) {
console.log(`- ${symbol} asset config`);
console.log(` - reserve address: ${address}`);
const reserveData = await protocolDataProvider.getReserveConfigurationData(address);
const tokensAddresses = await protocolDataProvider.getReserveTokensAddresses(address);
fields.forEach((field, index) => {
console.log(` - ${field}:`, reserveData[index].toString());
});
tokensFields.forEach((field, index) => {
console.log(` - ${field}:`, tokensAddresses[index]);
});
}
});

View File

@ -0,0 +1,12 @@
import { task } from 'hardhat/config';
import { getAaveProtocolDataProvider } from '../../helpers/contracts-getters';
task('print-config:fork', 'Deploy development enviroment')
.addFlag('verify', 'Verify contracts at Etherscan')
.setAction(async ({ verify }, DRE) => {
await DRE.run('set-DRE');
await DRE.run('aave:mainnet');
const dataProvider = await getAaveProtocolDataProvider();
await DRE.run('print-config', { dataProvider: dataProvider.address, pool: 'Aave' });
});

View File

@ -1,23 +1,23 @@
import {task} from 'hardhat/config';
import {loadPoolConfig, ConfigNames, getWethAddress} from '../../helpers/configuration';
import {ZERO_ADDRESS} from '../../helpers/constants';
import { task } from 'hardhat/config';
import { loadPoolConfig, ConfigNames, getWethAddress } from '../../helpers/configuration';
import { ZERO_ADDRESS } from '../../helpers/constants';
import {
getAddressById,
getLendingPool,
getLendingPoolAddressesProvider,
getLendingPoolConfiguratorProxy,
} from '../../helpers/contracts-getters';
import {getParamPerNetwork} from '../../helpers/contracts-helpers';
import {verifyContract} from '../../helpers/etherscan-verification';
import {eEthereumNetwork, ICommonConfiguration, IReserveParams} from '../../helpers/types';
import { getParamPerNetwork } from '../../helpers/contracts-helpers';
import { verifyContract } from '../../helpers/etherscan-verification';
import { eEthereumNetwork, ICommonConfiguration, IReserveParams } from '../../helpers/types';
task('verify:tokens', 'Deploy oracles for dev enviroment')
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
.setAction(async ({verify, all, pool}, localDRE) => {
.setAction(async ({ verify, all, pool }, localDRE) => {
await localDRE.run('set-DRE');
const network = localDRE.network.name as eEthereumNetwork;
const poolConfig = loadPoolConfig(pool);
const {ReserveAssets, ReservesConfig} = poolConfig as ICommonConfiguration;
const { ReserveAssets, ReservesConfig } = poolConfig as ICommonConfiguration;
const addressesProvider = await getLendingPoolAddressesProvider();
const lendingPoolProxy = await getLendingPool();
@ -40,6 +40,7 @@ task('verify:tokens', 'Deploy oracles for dev enviroment')
}
const {
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
@ -64,6 +65,7 @@ task('verify:tokens', 'Deploy oracles for dev enviroment')
console.log(`\n- Verifying Strategy rate...\n`);
await verifyContract(interestRateStrategyAddress, [
addressesProvider.address,
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,

View File

@ -2,6 +2,7 @@ import {TestEnv, makeSuite} from './helpers/make-suite';
import {APPROVAL_AMOUNT_LENDING_POOL, RAY} from '../helpers/constants';
import {convertToCurrencyDecimals} from '../helpers/contracts-helpers';
import {ProtocolErrors} from '../helpers/types';
import { strategyWETH } from '../markets/aave/reservesConfigs';
const {expect} = require('chai');
@ -58,7 +59,10 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
});
it('Freezes the ETH reserve', async () => {
const {configurator, pool, weth, helpersContract} = testEnv;
const {configurator, weth, helpersContract} = testEnv;
await configurator.freezeReserve(weth.address);
const {
decimals,
@ -75,12 +79,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
expect(isFrozen).to.be.equal(true);
expect(decimals).to.be.equal(18);
expect(ltv).to.be.equal(7500);
expect(liquidationThreshold).to.be.equal(8000);
expect(liquidationBonus).to.be.equal(10500);
expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(1000);
expect(decimals).to.be.equal(strategyWETH.reserveDecimals);
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});
it('Unfreezes the ETH reserve', async () => {
@ -102,12 +106,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
expect(isFrozen).to.be.equal(false);
expect(decimals).to.be.equal(18);
expect(ltv).to.be.equal(7500);
expect(liquidationThreshold).to.be.equal(8000);
expect(liquidationBonus).to.be.equal(10500);
expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(1000);
expect(decimals).to.be.equal(strategyWETH.reserveDecimals);
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});
it('Check the onlyAaveAdmin on freezeReserve ', async () => {
@ -144,12 +148,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(borrowingEnabled).to.be.equal(false);
expect(isActive).to.be.equal(true);
expect(isFrozen).to.be.equal(false);
expect(decimals).to.be.equal(18);
expect(ltv).to.be.equal(7500);
expect(liquidationThreshold).to.be.equal(8000);
expect(liquidationBonus).to.be.equal(10500);
expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(1000);
expect(decimals).to.be.equal(strategyWETH.reserveDecimals);
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});
it('Activates the ETH reserve for borrowing', async () => {
@ -172,12 +176,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
expect(isFrozen).to.be.equal(false);
expect(decimals).to.be.equal(18);
expect(ltv).to.be.equal(7500);
expect(liquidationThreshold).to.be.equal(8000);
expect(liquidationBonus).to.be.equal(10500);
expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(1000);
expect(decimals).to.be.equal(strategyWETH.reserveDecimals);
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
expect(variableBorrowIndex.toString()).to.be.equal(RAY);
});
@ -222,12 +226,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(liquidationThreshold).to.be.equal(0);
expect(liquidationBonus).to.be.equal(0);
expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(1000);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});
it('Activates the ETH reserve as collateral', async () => {
const {configurator, helpersContract, weth} = testEnv;
await configurator.configureReserveAsCollateral(weth.address, '7500', '8000', '10500');
await configurator.configureReserveAsCollateral(weth.address, '8000', '8250', '10500');
const {
decimals,
@ -244,12 +248,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
expect(isFrozen).to.be.equal(false);
expect(decimals).to.be.equal(18);
expect(ltv).to.be.equal(7500);
expect(liquidationThreshold).to.be.equal(8000);
expect(liquidationBonus).to.be.equal(10500);
expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(1000);
expect(decimals).to.be.equal(strategyWETH.reserveDecimals);
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});
it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => {
@ -280,12 +284,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
expect(isFrozen).to.be.equal(false);
expect(decimals).to.be.equal(18);
expect(ltv).to.be.equal(7500);
expect(liquidationThreshold).to.be.equal(8000);
expect(liquidationBonus).to.be.equal(10500);
expect(decimals).to.be.equal(strategyWETH.reserveDecimals);
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(false);
expect(reserveFactor).to.be.equal(1000);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});
it('Enables stable borrow rate on the ETH reserve', async () => {
@ -306,12 +310,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
expect(isFrozen).to.be.equal(false);
expect(decimals).to.be.equal(18);
expect(ltv).to.be.equal(7500);
expect(liquidationThreshold).to.be.equal(8000);
expect(liquidationBonus).to.be.equal(10500);
expect(decimals).to.be.equal(strategyWETH.reserveDecimals);
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(true);
expect(reserveFactor).to.be.equal(1000);
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});
it('Check the onlyAaveAdmin on disableReserveStableRate', async () => {
@ -348,11 +352,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
expect(isFrozen).to.be.equal(false);
expect(decimals).to.be.equal(18);
expect(ltv).to.be.equal(7500);
expect(liquidationThreshold).to.be.equal(8000);
expect(liquidationBonus).to.be.equal(10500);
expect(stableBorrowRateEnabled).to.be.equal(true);
expect(decimals).to.be.equal(strategyWETH.reserveDecimals);
expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral);
expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold);
expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus);
expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled);
expect(reserveFactor).to.be.equal(1000);
});

View File

@ -14,7 +14,7 @@ import {
getUniswapLiquiditySwapAdapter,
getUniswapRepayAdapter,
} from '../../helpers/contracts-getters';
import { tEthereumAddress } from '../../helpers/types';
import { eEthereumNetwork, tEthereumAddress } from '../../helpers/types';
import { LendingPool } from '../../types/LendingPool';
import { AaveProtocolDataProvider } from '../../types/AaveProtocolDataProvider';
import { MintableERC20 } from '../../types/MintableERC20';
@ -31,9 +31,11 @@ import { LendingPoolAddressesProviderRegistry } from '../../types/LendingPoolAdd
import { getEthersSigners } from '../../helpers/contracts-helpers';
import { UniswapLiquiditySwapAdapter } from '../../types/UniswapLiquiditySwapAdapter';
import { UniswapRepayAdapter } from '../../types/UniswapRepayAdapter';
import { getParamPerNetwork } from '../../helpers/contracts-helpers';
import { WETH9Mocked } from '../../types/WETH9Mocked';
import { WETHGateway } from '../../types/WETHGateway';
import { solidity } from 'ethereum-waffle';
import { AaveConfig } from '../../markets/aave';
chai.use(bignumberChai());
chai.use(almostEqual());
@ -108,9 +110,16 @@ export async function initializeMakeSuite() {
testEnv.configurator = await getLendingPoolConfiguratorProxy();
testEnv.oracle = await getPriceOracle();
testEnv.addressesProvider = await getLendingPoolAddressesProvider();
testEnv.registry = await getLendingPoolAddressesProviderRegistry();
if (process.env.MAINNET_FORK === 'true') {
testEnv.registry = await getLendingPoolAddressesProviderRegistry(
getParamPerNetwork(AaveConfig.ProviderRegistry, eEthereumNetwork.main)
);
} else {
testEnv.registry = await getLendingPoolAddressesProviderRegistry();
testEnv.oracle = await getPriceOracle();
}
testEnv.helpersContract = await getAaveProtocolDataProvider();

View File

@ -1,12 +1,5 @@
import BigNumber from 'bignumber.js';
import {
ONE_YEAR,
RAY,
MAX_UINT_AMOUNT,
OPTIMAL_UTILIZATION_RATE,
EXCESS_UTILIZATION_RATE,
PERCENTAGE_FACTOR,
} from '../../../helpers/constants';
import { ONE_YEAR, RAY, MAX_UINT_AMOUNT, PERCENTAGE_FACTOR } from '../../../helpers/constants';
import {
IReserveParams,
iAavePoolAssets,
@ -527,11 +520,10 @@ export const calcExpectedReserveDataAfterRepay = (
//due to accumulation errors, the total stable debt might be smaller than the last user debt.
//in this case we simply set the total supply and avg stable rate to 0.
if (expectedReserveData.principalStableDebt.lt(0)) {
expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = new BigNumber(
if (expectedReserveData.totalStableDebt.lt(0)) {
expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedReserveData.averageStableBorrowRate = new BigNumber(
0
);
expectedReserveData.averageStableBorrowRate = new BigNumber(0);
} else {
expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate(
reserveDataBeforeAction.averageStableBorrowRate,
@ -539,6 +531,15 @@ export const calcExpectedReserveDataAfterRepay = (
amountRepaidBN.negated(),
userDataBeforeAction.stableBorrowRate
);
//also due to accumulation errors, the final avg stable rate when the last user repays might be negative.
//if that is the case, it means a small leftover of total stable debt is left, which can be erased.
if (expectedReserveData.averageStableBorrowRate.lt(0)) {
expectedReserveData.principalStableDebt = expectedReserveData.totalStableDebt = expectedReserveData.averageStableBorrowRate = new BigNumber(
0
);
}
}
expectedReserveData.scaledVariableDebt = reserveDataBeforeAction.scaledVariableDebt;
@ -1210,6 +1211,7 @@ export const calcExpectedInterestRates = (
): BigNumber[] => {
const { reservesParams } = configuration;
const reserveIndex = Object.keys(reservesParams).findIndex((value) => value === reserveSymbol);
const [, reserveConfiguration] = (Object.entries(reservesParams) as [string, IReserveParams][])[
reserveIndex
@ -1218,10 +1220,12 @@ export const calcExpectedInterestRates = (
let stableBorrowRate: BigNumber = marketStableRate;
let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.baseVariableBorrowRate);
if (utilizationRate.gt(OPTIMAL_UTILIZATION_RATE)) {
const optimalRate = new BigNumber(reserveConfiguration.optimalUtilizationRate);
const excessRate = new BigNumber(RAY).minus(optimalRate);
if (utilizationRate.gt(optimalRate)) {
const excessUtilizationRateRatio = utilizationRate
.minus(OPTIMAL_UTILIZATION_RATE)
.rayDiv(EXCESS_UTILIZATION_RATE);
.minus(reserveConfiguration.optimalUtilizationRate)
.rayDiv(excessRate);
stableBorrowRate = stableBorrowRate
.plus(reserveConfiguration.stableRateSlope1)
@ -1237,13 +1241,13 @@ export const calcExpectedInterestRates = (
} else {
stableBorrowRate = stableBorrowRate.plus(
new BigNumber(reserveConfiguration.stableRateSlope1).rayMul(
utilizationRate.rayDiv(new BigNumber(OPTIMAL_UTILIZATION_RATE))
utilizationRate.rayDiv(new BigNumber(optimalRate))
)
);
variableBorrowRate = variableBorrowRate.plus(
utilizationRate
.rayDiv(OPTIMAL_UTILIZATION_RATE)
.rayDiv(optimalRate)
.rayMul(new BigNumber(reserveConfiguration.variableRateSlope1))
);
}

View File

@ -20,7 +20,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
LP_IS_PAUSED,
} = ProtocolErrors;
it('LIQUIDATION - Deposits WETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => {
it('Deposits WETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => {
const { dai, weth, users, pool, oracle } = testEnv;
const depositor = users[0];
const borrower = users[1];
@ -69,7 +69,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
const userGlobalDataAfter = await pool.getUserAccountData(borrower.address);
expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal(
'8000',
'8250',
'Invalid liquidation threshold'
);
@ -79,7 +79,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
).to.be.revertedWith(LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD);
});
it('LIQUIDATION - Drop the health factor below 1', async () => {
it('Drop the health factor below 1', async () => {
const { dai, users, pool, oracle } = testEnv;
const borrower = users[1];
@ -98,7 +98,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
);
});
it('LIQUIDATION - Tries to liquidate a different currency than the loan principal', async () => {
it('Tries to liquidate a different currency than the loan principal', async () => {
const { pool, users, weth } = testEnv;
const borrower = users[1];
//user 2 tries to borrow
@ -107,7 +107,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
).revertedWith(LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER);
});
it('LIQUIDATION - Tries to liquidate a different collateral than the borrower collateral', async () => {
it('Tries to liquidate a different collateral than the borrower collateral', async () => {
const { pool, dai, users } = testEnv;
const borrower = users[1];
@ -116,7 +116,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
).revertedWith(LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED);
});
it('LIQUIDATION - Liquidates the borrow', async () => {
it('Liquidates the borrow', async () => {
const { pool, dai, weth, aWETH, aDai, users, oracle, helpersContract, deployer } = testEnv;
const borrower = users[1];
@ -284,7 +284,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
await oracle.setAssetPrice(
usdc.address,
new BigNumber(usdcPrice.toString()).multipliedBy(1.2).toFixed(0)
new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0)
);
//mints dai to the liquidator

View File

@ -46,7 +46,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
await configurator.activateReserve(dai.address);
});
it('LIQUIDATION - Deposits WETH, borrows DAI', async () => {
it('Deposits WETH, borrows DAI', async () => {
const {dai, weth, users, pool, oracle} = testEnv;
const depositor = users[0];
const borrower = users[1];
@ -96,12 +96,12 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
const userGlobalDataAfter = await pool.getUserAccountData(borrower.address);
expect(userGlobalDataAfter.currentLiquidationThreshold.toString()).to.be.bignumber.equal(
'8000',
'8250',
INVALID_HF
);
});
it('LIQUIDATION - Drop the health factor below 1', async () => {
it('Drop the health factor below 1', async () => {
const {dai, weth, users, pool, oracle} = testEnv;
const borrower = users[1];
@ -109,7 +109,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
await oracle.setAssetPrice(
dai.address,
new BigNumber(daiPrice.toString()).multipliedBy(1.25).toFixed(0)
new BigNumber(daiPrice.toString()).multipliedBy(1.18).toFixed(0)
);
const userGlobalData = await pool.getUserAccountData(borrower.address);
@ -120,7 +120,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
);
});
it('LIQUIDATION - Liquidates the borrow', async () => {
it('Liquidates the borrow', async () => {
const {dai, weth, users, pool, oracle, helpersContract} = testEnv;
const liquidator = users[3];
const borrower = users[1];
@ -280,7 +280,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
//drops HF below 1
await oracle.setAssetPrice(
usdc.address,
new BigNumber(usdcPrice.toString()).multipliedBy(1.2).toFixed(0)
new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0)
);
//mints dai to the liquidator
@ -402,7 +402,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
//drops HF below 1
await oracle.setAssetPrice(
usdc.address,
new BigNumber(usdcPrice.toString()).multipliedBy(1.12).toFixed(0)
new BigNumber(usdcPrice.toString()).multipliedBy(1.14).toFixed(0)
);
//mints usdc to the liquidator