mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'master' into feat/uniswap-adapter-flashloan
# Conflicts: # helpers/contracts-deployments.ts # helpers/types.ts # test/__setup.spec.ts # test/helpers/make-suite.ts
This commit is contained in:
commit
3f779e2e9f
buidler.config.tscoverage.jsondeployed-contracts.jsonhardhat.config.ts
config
contracts
configuration
deployments
interfaces
lendingpool
libraries
configuration
helpers
logic
misc
ChainlinkProxyPriceProvider.solUiPoolDataProvider.solWETHGateway.solWalletBalanceProvider.sol
interfaces
mocks
attacks
dependencies/weth
flashloan
tokens
tokenization
helpers
configuration.tscontracts-deployments.tscontracts-getters.tscontracts-helpers.tsetherscan-verification.tsinit-helpers.tsmisc-utils.tstypes.ts
package-lock.jsonpackage.jsonspecs/harness
tasks
deployments
dev
1_mock_tokens.ts2_address_provider_registry.ts3_lending_pool.ts4_oracles.ts5_initialize.ts6_wallet_balance_provider.ts
full
migrations
misc
test
__setup.spec.tsatoken-permit.spec.tsconfigurator.spec.tsdelegation-aware-atoken.spec.tsflashloan.spec.ts
tsconfig.jsonhelpers
lending-pool-addresses-provider.spec.tsliquidation-atoken.spec.tsliquidation-underlying.spec.tspausable-functions.spec.tsstable-token.spec.tstoken-distributor.spec.tsupgradeability.spec.tsvariable-debt-token.spec.tsweth-gateway.spec.ts
|
@ -1,10 +1,13 @@
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import {usePlugin} from '@nomiclabs/buidler/config';
|
||||
import {usePlugin, task} from '@nomiclabs/buidler/config';
|
||||
// @ts-ignore
|
||||
import {accounts} from './test-wallets.js';
|
||||
import {eEthereumNetwork} from './helpers/types';
|
||||
import {BUIDLEREVM_CHAINID, COVERAGE_CHAINID} from './helpers/buidler-constants';
|
||||
import {setDRE} from './helpers/misc-utils';
|
||||
|
||||
require('dotenv').config();
|
||||
|
||||
usePlugin('@nomiclabs/buidler-ethers');
|
||||
usePlugin('buidler-typechain');
|
||||
|
@ -22,15 +25,12 @@ const ETHERSCAN_KEY = process.env.ETHERSCAN_KEY || '';
|
|||
const MNEMONIC_PATH = "m/44'/60'/0'/0";
|
||||
const MNEMONIC = process.env.MNEMONIC || '';
|
||||
|
||||
// Prevent to load scripts before compilation and typechain
|
||||
if (!SKIP_LOAD) {
|
||||
['misc', 'migrations', 'dev', 'full'].forEach((folder) => {
|
||||
const tasksPath = path.join(__dirname, 'tasks', folder);
|
||||
fs.readdirSync(tasksPath)
|
||||
.filter((pth) => pth.includes('.ts'))
|
||||
.forEach((task) => require(`${tasksPath}/${task}`));
|
||||
});
|
||||
}
|
||||
task(`set-DRE`, `Inits the DRE, to have access to all the plugins' objects`).setAction(
|
||||
async (_, _DRE) => {
|
||||
setDRE(_DRE);
|
||||
return _DRE;
|
||||
}
|
||||
);
|
||||
|
||||
const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number) => {
|
||||
return {
|
||||
|
|
303
config/aave.ts
303
config/aave.ts
|
@ -1,8 +1,29 @@
|
|||
import BigNumber from 'bignumber.js';
|
||||
import {oneRay} from '../helpers/constants';
|
||||
import {oneRay, ZERO_ADDRESS} from '../helpers/constants';
|
||||
import {IAaveConfiguration, EthereumNetwork, eEthereumNetwork} from '../helpers/types';
|
||||
|
||||
import {CommonsConfig} from './commons';
|
||||
import {
|
||||
stablecoinStrategyBUSD,
|
||||
stablecoinStrategyDAI,
|
||||
stablecoinStrategySUSD,
|
||||
stablecoinStrategyTUSD,
|
||||
stablecoinStrategyUSDC,
|
||||
stablecoinStrategyUSDT,
|
||||
strategyAAVE,
|
||||
strategyBase,
|
||||
strategyKNC,
|
||||
strategyLINK,
|
||||
strategyMANA,
|
||||
strategyMKR,
|
||||
strategyREN,
|
||||
strategyREP,
|
||||
strategySNX,
|
||||
strategyUNI,
|
||||
strategyWBTC,
|
||||
strategyWETH,
|
||||
strategyYFI,
|
||||
} from './reservesConfigs';
|
||||
|
||||
// ----------------
|
||||
// POOL--SPECIFIC PARAMS
|
||||
|
@ -12,250 +33,32 @@ export const AaveConfig: IAaveConfiguration = {
|
|||
...CommonsConfig,
|
||||
ConfigName: 'Aave',
|
||||
ProviderId: 1,
|
||||
ReserveSymbols: [
|
||||
'WETH',
|
||||
'DAI',
|
||||
'LEND',
|
||||
'TUSD',
|
||||
'BAT',
|
||||
'USDC',
|
||||
'USDT',
|
||||
'SUSD',
|
||||
'ZRX',
|
||||
'MKR',
|
||||
'WBTC',
|
||||
'LINK',
|
||||
'KNC',
|
||||
'MANA',
|
||||
'REP',
|
||||
'SNX',
|
||||
'BUSD',
|
||||
],
|
||||
ReservesConfig: {
|
||||
DAI: {
|
||||
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.05).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.16).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '7500',
|
||||
liquidationThreshold: '8000',
|
||||
liquidationBonus: '10500',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
TUSD: {
|
||||
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.14).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '7500',
|
||||
liquidationThreshold: '8000',
|
||||
liquidationBonus: '10500',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
USDC: {
|
||||
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.16).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '7500',
|
||||
liquidationThreshold: '8000',
|
||||
liquidationBonus: '10500',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '6',
|
||||
},
|
||||
USDT: {
|
||||
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.14).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '-1',
|
||||
liquidationThreshold: '8000',
|
||||
liquidationBonus: '10500',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '6',
|
||||
},
|
||||
SUSD: {
|
||||
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.14).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '-1',
|
||||
liquidationThreshold: '8000',
|
||||
liquidationBonus: '10500',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: false,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
LEND: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).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',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
BAT: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '6000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
WETH: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '7500',
|
||||
liquidationThreshold: '8000',
|
||||
liquidationBonus: '10500',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
LINK: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '6500',
|
||||
liquidationThreshold: '7000',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
WBTC: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).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',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '8',
|
||||
},
|
||||
KNC: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '6000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
REP: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '6000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
MKR: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '6000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
MANA: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '6000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
ZRX: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '6000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
SNX: {
|
||||
baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.12).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '-1',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: false,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
BUSD: {
|
||||
baseVariableBorrowRate: new BigNumber(0.01).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope1: new BigNumber(0.14).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
baseLTVAsCollateral: '-1',
|
||||
liquidationThreshold: '8000',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: false,
|
||||
reserveDecimals: '18',
|
||||
},
|
||||
DAI: stablecoinStrategyDAI,
|
||||
TUSD: stablecoinStrategyTUSD,
|
||||
USDC: stablecoinStrategyUSDC,
|
||||
USDT: stablecoinStrategyUSDT,
|
||||
SUSD: stablecoinStrategySUSD,
|
||||
AAVE: strategyAAVE,
|
||||
BAT: strategyBase,
|
||||
WETH: strategyWETH,
|
||||
LINK: strategyLINK,
|
||||
WBTC: strategyWBTC,
|
||||
KNC: strategyKNC,
|
||||
REP: strategyREP,
|
||||
MKR: strategyMKR,
|
||||
MANA: strategyMANA,
|
||||
ZRX: strategyBase,
|
||||
SNX: strategySNX,
|
||||
YFI: strategyYFI,
|
||||
UNI: strategyUNI,
|
||||
BUSD: stablecoinStrategyBUSD,
|
||||
REN: strategyREN,
|
||||
ENJ: strategyREN,
|
||||
},
|
||||
ReserveAssets: {
|
||||
[eEthereumNetwork.buidlerevm]: {},
|
||||
[eEthereumNetwork.hardhat]: {},
|
||||
[eEthereumNetwork.coverage]: {},
|
||||
[EthereumNetwork.kovan]: {
|
||||
WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c',
|
||||
|
@ -264,7 +67,7 @@ export const AaveConfig: IAaveConfiguration = {
|
|||
USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422',
|
||||
USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4',
|
||||
SUSD: '0xD868790F57B39C9B2B51b12de046975f986675f9',
|
||||
LEND: '0x690eAcA024935Aaff9B14b9FF9e9C8757a281f3C',
|
||||
AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af',
|
||||
BAT: '0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738',
|
||||
REP: '0x260071C8D61DAf730758f8BD0d6370353956AE0E',
|
||||
MKR: '0x61e4CAE3DA7FD189e52a4879C7B8067D7C2Cc0FA',
|
||||
|
@ -275,6 +78,10 @@ export const AaveConfig: IAaveConfiguration = {
|
|||
ZRX: '0xD0d76886cF8D952ca26177EB7CfDf83bad08C00C',
|
||||
SNX: '0x7FDb81B0b8a010dd4FFc57C3fecbf145BA8Bd947',
|
||||
BUSD: '0x4c6E1EFC12FDfD568186b7BAEc0A43fFfb4bCcCf',
|
||||
REN: '0x5eebf65A6746eed38042353Ba84c8e37eD58Ac6f',
|
||||
YFI: '0xb7c325266ec274fEb1354021D27FA3E3379D840d',
|
||||
UNI: '0x075A36BA8846C6B6F53644fDd3bf17E5151789DC',
|
||||
ENJ: '0xC64f90Cd7B564D3ab580eb20a102A8238E218be2',
|
||||
},
|
||||
[EthereumNetwork.ropsten]: {
|
||||
WETH: '0xc778417e063141139fce010982780140aa0cd5ab',
|
||||
|
@ -283,7 +90,7 @@ export const AaveConfig: IAaveConfiguration = {
|
|||
USDC: '0x851dEf71f0e6A903375C1e536Bd9ff1684BAD802',
|
||||
USDT: '0xB404c51BBC10dcBE948077F18a4B8E553D160084',
|
||||
SUSD: '0xc374eB17f665914c714Ac4cdC8AF3a3474228cc5',
|
||||
LEND: '0xB47F338EC1e3857BB188E63569aeBAB036EE67c6',
|
||||
AAVE: '',
|
||||
BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d',
|
||||
REP: '0xBeb13523503d35F9b3708ca577CdCCAdbFB236bD',
|
||||
MKR: '0x2eA9df3bABe04451c9C3B06a2c844587c59d9C37',
|
||||
|
@ -294,6 +101,10 @@ export const AaveConfig: IAaveConfiguration = {
|
|||
ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959',
|
||||
SNX: '0xF80Aa7e2Fda4DA065C55B8061767F729dA1476c7',
|
||||
BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6',
|
||||
REN: ZERO_ADDRESS,
|
||||
YFI: ZERO_ADDRESS,
|
||||
UNI: ZERO_ADDRESS,
|
||||
ENJ: ZERO_ADDRESS,
|
||||
},
|
||||
[EthereumNetwork.main]: {
|
||||
WETH: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
||||
|
@ -302,7 +113,7 @@ export const AaveConfig: IAaveConfiguration = {
|
|||
USDC: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||
USDT: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
||||
SUSD: '0x57ab1ec28d129707052df4df418d58a2d46d5f51',
|
||||
LEND: '0x80fB784B7eD66730e8b1DBd9820aFD29931aab03',
|
||||
AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9',
|
||||
BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef',
|
||||
REP: '0x1985365e9f78359a9B6AD760e32412f4a445E862',
|
||||
MKR: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2',
|
||||
|
@ -313,6 +124,10 @@ export const AaveConfig: IAaveConfiguration = {
|
|||
ZRX: '0xe41d2489571d322189246dafa5ebde1f4699f498',
|
||||
SNX: '0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F',
|
||||
BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53',
|
||||
REN: '0x408e41876cCCDC0F92210600ef50372656052a38',
|
||||
YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e',
|
||||
UNI: '0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984',
|
||||
ENJ: '0xF629cBd94d3791C9250152BD8dfBDF380E2a3B9c',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import BigNumber from 'bignumber.js';
|
||||
import {oneEther, oneRay, RAY} from '../helpers/constants';
|
||||
import {zeroPad} from 'ethers/lib/utils';
|
||||
import {oneEther, oneRay, RAY, ZERO_ADDRESS} from '../helpers/constants';
|
||||
import {ICommonConfiguration, EthereumNetwork, eEthereumNetwork} from '../helpers/types';
|
||||
|
||||
const MOCK_CHAINLINK_AGGREGATORS_PRICES = {
|
||||
DAI: oneEther.multipliedBy('0.00369068412860').toFixed(),
|
||||
TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(),
|
||||
USDC: oneEther.multipliedBy('0.00367714136416').toFixed(),
|
||||
LEND: oneEther.multipliedBy('0.00003620948469').toFixed(),
|
||||
AAVE: oneEther.multipliedBy('0.003620948469').toFixed(),
|
||||
BAT: oneEther.multipliedBy('0.00137893825230').toFixed(),
|
||||
USDT: oneEther.multipliedBy('0.00369068412860').toFixed(),
|
||||
SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(),
|
||||
|
@ -21,6 +22,10 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = {
|
|||
BUSD: oneEther.multipliedBy('0.00736484').toFixed(),
|
||||
WETH: oneEther.toFixed(),
|
||||
USD: '5848466240000000',
|
||||
YFI: oneEther.multipliedBy('22.407436').toFixed(),
|
||||
REN: oneEther.multipliedBy('0.00065133').toFixed(),
|
||||
UNI: oneEther.multipliedBy('0.00536479').toFixed(),
|
||||
ENJ: oneEther.multipliedBy('0.00029560').toFixed(),
|
||||
UNI_DAI_ETH: oneEther.multipliedBy('2.1').toFixed(),
|
||||
UNI_USDC_ETH: oneEther.multipliedBy('2.1').toFixed(),
|
||||
UNI_SETH_ETH: oneEther.multipliedBy('2.1').toFixed(),
|
||||
|
@ -35,7 +40,6 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = {
|
|||
export const CommonsConfig: ICommonConfiguration = {
|
||||
ConfigName: 'Commons',
|
||||
ProviderId: 0,
|
||||
ReserveSymbols: [],
|
||||
ProtocolGlobalParams: {
|
||||
OptimalUtilizationRate: new BigNumber(0.8).times(RAY),
|
||||
ExcessUtilizationRate: new BigNumber(0.2).times(RAY),
|
||||
|
@ -83,7 +87,7 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
BAT: {
|
||||
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
|
||||
},
|
||||
LEND: {
|
||||
AAVE: {
|
||||
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
|
||||
},
|
||||
LINK: {
|
||||
|
@ -110,6 +114,15 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
SNX: {
|
||||
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
|
||||
},
|
||||
YFI: {
|
||||
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
|
||||
},
|
||||
REN: {
|
||||
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
|
||||
},
|
||||
UNI: {
|
||||
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
|
||||
},
|
||||
BUSD: {
|
||||
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
|
||||
},
|
||||
|
@ -118,38 +131,53 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
// COMMON PROTOCOL ADDRESSES ACROSS POOLS
|
||||
// ----------------
|
||||
|
||||
// If lendingPoolManagerAddress is set, will take priority over lendingPoolManagerAddressIndex
|
||||
AaveAdmin: {
|
||||
// If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex
|
||||
PoolAdmin: {
|
||||
[eEthereumNetwork.coverage]: undefined,
|
||||
[eEthereumNetwork.buidlerevm]: undefined,
|
||||
[eEthereumNetwork.coverage]: undefined,
|
||||
[eEthereumNetwork.hardhat]: undefined,
|
||||
[eEthereumNetwork.kovan]: undefined,
|
||||
[eEthereumNetwork.ropsten]: undefined,
|
||||
[eEthereumNetwork.main]: undefined,
|
||||
},
|
||||
PoolAdminIndex: 0,
|
||||
EmergencyAdmin: {
|
||||
[eEthereumNetwork.hardhat]: undefined,
|
||||
[eEthereumNetwork.coverage]: undefined,
|
||||
[eEthereumNetwork.buidlerevm]: undefined,
|
||||
[eEthereumNetwork.kovan]: undefined,
|
||||
[eEthereumNetwork.ropsten]: undefined,
|
||||
[eEthereumNetwork.main]: undefined,
|
||||
},
|
||||
AaveAdminIndex: 0,
|
||||
EmergencyAdminIndex: 1,
|
||||
ProviderRegistry: {
|
||||
[eEthereumNetwork.kovan]: '',
|
||||
[eEthereumNetwork.ropsten]: '',
|
||||
[eEthereumNetwork.main]: '',
|
||||
[eEthereumNetwork.coverage]: '',
|
||||
[eEthereumNetwork.hardhat]: '',
|
||||
[eEthereumNetwork.buidlerevm]: '',
|
||||
},
|
||||
LendingRateOracle: {
|
||||
[eEthereumNetwork.coverage]: '',
|
||||
[eEthereumNetwork.hardhat]: '',
|
||||
[eEthereumNetwork.buidlerevm]: '',
|
||||
[eEthereumNetwork.kovan]: '0xdcde9bb6a49e37fa433990832ab541ae2d4feb4a',
|
||||
[eEthereumNetwork.kovan]: '0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a',
|
||||
[eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b',
|
||||
[eEthereumNetwork.main]: '0x4d728a4496e4de35f218d5a214366bde3a62b51c',
|
||||
},
|
||||
TokenDistributor: {
|
||||
[eEthereumNetwork.coverage]: '',
|
||||
[eEthereumNetwork.buidlerevm]: '',
|
||||
[eEthereumNetwork.hardhat]: '',
|
||||
[EthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708',
|
||||
[EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c',
|
||||
[EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae',
|
||||
},
|
||||
ChainlinkProxyPriceProvider: {
|
||||
[eEthereumNetwork.coverage]: '',
|
||||
[eEthereumNetwork.hardhat]: '',
|
||||
[eEthereumNetwork.buidlerevm]: '',
|
||||
[EthereumNetwork.kovan]: '0x276C4793F2EE3D5Bf18C5b879529dD4270BA4814',
|
||||
[EthereumNetwork.ropsten]: '0x657372A559c30d236F011239fF9fbB6D76718271',
|
||||
|
@ -157,6 +185,7 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
},
|
||||
FallbackOracle: {
|
||||
[eEthereumNetwork.coverage]: '',
|
||||
[eEthereumNetwork.hardhat]: '',
|
||||
[eEthereumNetwork.buidlerevm]: '',
|
||||
[EthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe',
|
||||
[EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d',
|
||||
|
@ -164,6 +193,7 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
},
|
||||
ChainlinkAggregator: {
|
||||
[eEthereumNetwork.coverage]: {},
|
||||
[eEthereumNetwork.hardhat]: {},
|
||||
[eEthereumNetwork.buidlerevm]: {},
|
||||
[EthereumNetwork.kovan]: {
|
||||
DAI: '0x6F47077D3B6645Cb6fb7A29D280277EC1e5fFD90',
|
||||
|
@ -171,7 +201,7 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
USDC: '0x672c1C0d1130912D83664011E7960a42E8cA05D5',
|
||||
USDT: '0xCC833A6522721B3252e7578c5BCAF65738B75Fc3',
|
||||
SUSD: '0xa353F8b083F7575cfec443b5ad585D42f652E9F7',
|
||||
LEND: '0xdce38940264dfbc01ad1486c21764948e511947e',
|
||||
AAVE: '0xd04647B7CB523bb9f26730E9B6dE1174db7591Ad',
|
||||
BAT: '0x2c8d01771CCDca47c103194C5860dbEA2fE61626',
|
||||
REP: '0x09F4A94F44c29d4967C761bBdB89f5bD3E2c09E6',
|
||||
MKR: '0x14D7714eC44F44ECD0098B39e642b246fB2c38D0',
|
||||
|
@ -183,6 +213,10 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
SNX: '0x775E76cca1B5bc903c9a8C6f77416A35E5744664',
|
||||
BUSD: '0x63294A05C9a81b1A40CAD3f2ff30617111630393',
|
||||
USD: '0xD21912D8762078598283B14cbA40Cb4bFCb87581',
|
||||
YFI: '0xe45f3ed2218E7e411bf8DFdE66069e57F46b26eF',
|
||||
REN: '0xF1939BECE7708382b5fb5e559f630CB8B39a10ee',
|
||||
UNI: '0x17756515f112429471F86f98D5052aCB6C47f6ee',
|
||||
ENJ: '0xfaDbe2ee798889F02d1d39eDaD98Eff4c7fe95D4',
|
||||
UNI_DAI_ETH: '0x0338C40020Bf886c11406115fD1ba205Ef1D9Ff9',
|
||||
UNI_USDC_ETH: '0x7f5E5D34591e9a70D187BBA94260C30B92aC0961',
|
||||
UNI_SETH_ETH: '0xc5F1eA001c1570783b3af418fa775237Eb129EDC',
|
||||
|
@ -196,7 +230,7 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
USDC: '0xe1480303dde539e2c241bdc527649f37c9cbef7d',
|
||||
USDT: '0xc08fe0c4d97ccda6b40649c6da621761b628c288',
|
||||
SUSD: '0xe054b4aee7ac7645642dd52f1c892ff0128c98f0',
|
||||
LEND: '0xf7b4834fe443d1E04D757b4b089b35F5A90F2847',
|
||||
AAVE: '',
|
||||
BAT: '0xafd8186c962daf599f171b8600f3e19af7b52c92',
|
||||
REP: '0xa949ee9ba80c0f381481f2eab538bc5547a5ac67',
|
||||
MKR: '0x811B1f727F8F4aE899774B568d2e72916D91F392',
|
||||
|
@ -208,6 +242,10 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
SNX: '0xA95674a8Ed9aa9D2E445eb0024a9aa05ab44f6bf',
|
||||
BUSD: '0x0A32D96Ff131cd5c3E0E5AAB645BF009Eda61564',
|
||||
USD: '0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507',
|
||||
YFI: ZERO_ADDRESS,
|
||||
REN: ZERO_ADDRESS,
|
||||
UNI: ZERO_ADDRESS,
|
||||
ENJ: ZERO_ADDRESS,
|
||||
UNI_DAI_ETH: '0x16048819e3f77b7112eB033624A0bA9d33743028',
|
||||
UNI_USDC_ETH: '0x6952A2678D574073DB97963886c2F38CD09C8Ba3',
|
||||
UNI_SETH_ETH: '0x23Ee5188806BD2D31103368B0EA0259bc6706Af1',
|
||||
|
@ -221,7 +259,7 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
USDC: '0xdE54467873c3BCAA76421061036053e371721708',
|
||||
USDT: '0xa874fe207DF445ff19E7482C746C4D3fD0CB9AcE',
|
||||
SUSD: '0x6d626Ff97f0E89F6f983dE425dc5B24A18DE26Ea',
|
||||
LEND: '0x1EeaF25f2ECbcAf204ECADc8Db7B0db9DA845327',
|
||||
AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012',
|
||||
BAT: '0x9b4e2579895efa2b4765063310Dc4109a7641129',
|
||||
REP: '0xb8b513d9cf440C1b6f5C7142120d611C94fC220c',
|
||||
MKR: '0xda3d675d50ff6c555973c4f0424964e1f6a4e7d3',
|
||||
|
@ -233,6 +271,10 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
SNX: '0xE23d1142dE4E83C08bb048bcab54d50907390828',
|
||||
BUSD: '0x5d4BB541EED49D0290730b4aB332aA46bd27d888',
|
||||
USD: '0x59b826c214aBa7125bFA52970d97736c105Cc375',
|
||||
YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4',
|
||||
REN: '0x3147D7203354Dc06D9fd350c7a2437bcA92387a4',
|
||||
UNI: '0xD6aA3D25116d8dA79Ea0246c4826EB951872e02e',
|
||||
ENJ: '0x24D9aB51950F3d62E9144fdC2f3135DAA6Ce8D1B',
|
||||
UNI_DAI_ETH: '0x1bAB293850289Bf161C5DA79ff3d1F02A950555b',
|
||||
UNI_USDC_ETH: '0x444315Ee92F2bb3579293C17B07194227fA99bF0',
|
||||
UNI_SETH_ETH: '0x517D40E49660c7705b2e99eEFA6d7B0E9Ba5BF10',
|
||||
|
@ -243,6 +285,7 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
},
|
||||
ReserveAssets: {
|
||||
[eEthereumNetwork.coverage]: {},
|
||||
[eEthereumNetwork.hardhat]: {},
|
||||
[eEthereumNetwork.buidlerevm]: {},
|
||||
[EthereumNetwork.main]: {},
|
||||
[EthereumNetwork.kovan]: {},
|
||||
|
@ -252,17 +295,28 @@ export const CommonsConfig: ICommonConfiguration = {
|
|||
ATokenDomainSeparator: {
|
||||
[eEthereumNetwork.coverage]:
|
||||
'0x95b73a72c6ecf4ccbbba5178800023260bad8e75cdccdb8e4827a2977a37c820',
|
||||
[eEthereumNetwork.hardhat]:
|
||||
'0x92d0d54f437b6e70937ecba8ac80fc3b6767cf26bc725820e937d5a78427c2d1',
|
||||
[eEthereumNetwork.buidlerevm]:
|
||||
'0x76cbbf8aa4b11a7c207dd79ccf8c394f59475301598c9a083f8258b4fafcfa86',
|
||||
'0x92d0d54f437b6e70937ecba8ac80fc3b6767cf26bc725820e937d5a78427c2d1',
|
||||
[eEthereumNetwork.kovan]: '',
|
||||
[eEthereumNetwork.ropsten]: '',
|
||||
[eEthereumNetwork.main]: '',
|
||||
},
|
||||
ProxyPriceProvider: {
|
||||
[eEthereumNetwork.coverage]: '',
|
||||
[eEthereumNetwork.hardhat]: '',
|
||||
[eEthereumNetwork.buidlerevm]: '',
|
||||
[eEthereumNetwork.kovan]: '0x276C4793F2EE3D5Bf18C5b879529dD4270BA4814',
|
||||
[eEthereumNetwork.kovan]: '0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1',
|
||||
[eEthereumNetwork.ropsten]: '',
|
||||
[eEthereumNetwork.main]: '',
|
||||
},
|
||||
WETH: {
|
||||
[eEthereumNetwork.coverage]: '', // deployed in local evm
|
||||
[eEthereumNetwork.hardhat]: '', // deployed in local evm
|
||||
[eEthereumNetwork.buidlerevm]: '', // deployed in local evm
|
||||
[eEthereumNetwork.kovan]: '0xd0a1e359811322d97991e03f863a0c30c2cf029c',
|
||||
[eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab',
|
||||
[eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
|
||||
},
|
||||
};
|
||||
|
|
212
config/reservesConfigs.ts
Normal file
212
config/reservesConfigs.ts
Normal file
|
@ -0,0 +1,212 @@
|
|||
import BigNumber from 'bignumber.js';
|
||||
import {oneRay} from '../helpers/constants';
|
||||
import {IReserveParams} from '../helpers/types';
|
||||
|
||||
export const strategyBase: IReserveParams = {
|
||||
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: '6000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
};
|
||||
|
||||
export const stablecoinStrategyCentralized: IReserveParams = {
|
||||
baseVariableBorrowRate: new BigNumber(0.01).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',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '6',
|
||||
};
|
||||
|
||||
export const stablecoinStrategyBase: IReserveParams = {
|
||||
baseVariableBorrowRate: new BigNumber(0.01).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',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
};
|
||||
|
||||
export const stablecoinStrategyDAI: IReserveParams = {
|
||||
...stablecoinStrategyBase,
|
||||
};
|
||||
|
||||
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 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(),
|
||||
stableBorrowRateEnabled: false,
|
||||
stableRateSlope1: new BigNumber(0.14).multipliedBy(oneRay).toFixed(),
|
||||
stableRateSlope2: new BigNumber(0.6).multipliedBy(oneRay).toFixed(),
|
||||
};
|
||||
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: false,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '6',
|
||||
};
|
||||
|
||||
export const stablecoinStrategySUSD: IReserveParams = {
|
||||
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: false,
|
||||
stableBorrowRateEnabled: false,
|
||||
reserveDecimals: '18',
|
||||
};
|
||||
|
||||
export const strategyAAVE: IReserveParams = {
|
||||
...strategyBase,
|
||||
baseLTVAsCollateral: '5000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: false,
|
||||
stableBorrowRateEnabled: false,
|
||||
reserveDecimals: '18',
|
||||
};
|
||||
|
||||
export const strategyWETH: IReserveParams = {
|
||||
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: '7500',
|
||||
liquidationThreshold: '8000',
|
||||
liquidationBonus: '10500',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '18',
|
||||
};
|
||||
|
||||
export const strategyLINK: IReserveParams = {
|
||||
...strategyBase,
|
||||
baseLTVAsCollateral: '6500',
|
||||
liquidationThreshold: '7000',
|
||||
};
|
||||
|
||||
export const strategyWBTC: IReserveParams = {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(0.5).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',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: true,
|
||||
reserveDecimals: '8',
|
||||
};
|
||||
|
||||
export const strategyKNC: IReserveParams = {
|
||||
...strategyBase,
|
||||
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
|
||||
};
|
||||
|
||||
export const strategyREP: IReserveParams = {
|
||||
...strategyBase,
|
||||
baseLTVAsCollateral: '3500',
|
||||
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
|
||||
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
|
||||
borrowingEnabled: false,
|
||||
};
|
||||
|
||||
export const strategyMKR: IReserveParams = {
|
||||
...strategyBase,
|
||||
baseLTVAsCollateral: '3500',
|
||||
};
|
||||
|
||||
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 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 strategyENJ: IReserveParams = {
|
||||
...strategyBase,
|
||||
baseLTVAsCollateral: '5500',
|
||||
stableBorrowRateEnabled: false,
|
||||
};
|
||||
|
||||
export const strategyREN: IReserveParams = {
|
||||
...strategyBase,
|
||||
baseLTVAsCollateral: '5000',
|
||||
liquidationThreshold: '6500',
|
||||
liquidationBonus: '11000',
|
||||
borrowingEnabled: true,
|
||||
stableBorrowRateEnabled: false,
|
||||
};
|
||||
|
||||
export const strategyGovernanceTokens: IReserveParams = {
|
||||
...strategyBase,
|
||||
baseLTVAsCollateral: '4000',
|
||||
liquidationBonus: '11500',
|
||||
};
|
||||
export const strategyYFI: IReserveParams = {
|
||||
...strategyGovernanceTokens,
|
||||
};
|
||||
|
||||
export const strategyUNI: IReserveParams = {
|
||||
...strategyGovernanceTokens,
|
||||
stableBorrowRateEnabled: false,
|
||||
};
|
|
@ -12,18 +12,6 @@ export const UniswapConfig: IUniswapConfiguration = {
|
|||
...CommonsConfig,
|
||||
ConfigName: 'Uniswap',
|
||||
ProviderId: 2,
|
||||
ReserveSymbols: [
|
||||
'WETH',
|
||||
'DAI',
|
||||
'USDC',
|
||||
'USDT',
|
||||
'UNI_DAI_ETH',
|
||||
'UNI_USDC_ETH',
|
||||
'UNI_SETH_ETH',
|
||||
'UNI_LINK_ETH',
|
||||
'UNI_MKR_ETH',
|
||||
'UNI_LEND_ETH',
|
||||
],
|
||||
ReservesConfig: {
|
||||
WETH: {
|
||||
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
|
||||
|
@ -158,6 +146,7 @@ export const UniswapConfig: IUniswapConfiguration = {
|
|||
},
|
||||
ChainlinkAggregator: {
|
||||
[eEthereumNetwork.buidlerevm]: {},
|
||||
[eEthereumNetwork.hardhat]: {},
|
||||
[eEthereumNetwork.coverage]: {},
|
||||
[EthereumNetwork.kovan]: {
|
||||
DAI: '0x6F47077D3B6645Cb6fb7A29D280277EC1e5fFD90',
|
||||
|
@ -194,6 +183,7 @@ export const UniswapConfig: IUniswapConfiguration = {
|
|||
},
|
||||
},
|
||||
ReserveAssets: {
|
||||
[eEthereumNetwork.hardhat]: {},
|
||||
[eEthereumNetwork.buidlerevm]: {},
|
||||
[eEthereumNetwork.coverage]: {},
|
||||
[EthereumNetwork.kovan]: {
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
pragma solidity ^0.6.8;
|
||||
|
||||
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
|
||||
import {
|
||||
InitializableImmutableAdminUpgradeabilityProxy
|
||||
} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
|
||||
|
||||
// Prettier ignore to prevent buidler flatter bug
|
||||
// prettier-ignore
|
||||
import {InitializableImmutableAdminUpgradeabilityProxy} from '../libraries/aave-upgradeability/InitializableImmutableAdminUpgradeabilityProxy.sol';
|
||||
|
||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||
|
||||
|
@ -20,7 +21,8 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
|
|||
|
||||
bytes32 private constant LENDING_POOL = 'LENDING_POOL';
|
||||
bytes32 private constant LENDING_POOL_CONFIGURATOR = 'LENDING_POOL_CONFIGURATOR';
|
||||
bytes32 private constant AAVE_ADMIN = 'AAVE_ADMIN';
|
||||
bytes32 private constant POOL_ADMIN = 'POOL_ADMIN';
|
||||
bytes32 private constant EMERGENCY_ADMIN = 'EMERGENCY_ADMIN';
|
||||
bytes32 private constant LENDING_POOL_COLLATERAL_MANAGER = 'COLLATERAL_MANAGER';
|
||||
bytes32 private constant PRICE_ORACLE = 'PRICE_ORACLE';
|
||||
bytes32 private constant LENDING_RATE_ORACLE = 'LENDING_RATE_ORACLE';
|
||||
|
@ -113,13 +115,22 @@ contract LendingPoolAddressesProvider is Ownable, ILendingPoolAddressesProvider
|
|||
* hence the upgradable proxy pattern is not used
|
||||
**/
|
||||
|
||||
function getAaveAdmin() external override view returns (address) {
|
||||
return getAddress(AAVE_ADMIN);
|
||||
function getPoolAdmin() external override view returns (address) {
|
||||
return getAddress(POOL_ADMIN);
|
||||
}
|
||||
|
||||
function setAaveAdmin(address aaveAdmin) external override onlyOwner {
|
||||
_addresses[AAVE_ADMIN] = aaveAdmin;
|
||||
emit AaveAdminUpdated(aaveAdmin);
|
||||
function setPoolAdmin(address admin) external override onlyOwner {
|
||||
_addresses[POOL_ADMIN] = admin;
|
||||
emit ConfigurationAdminUpdated(admin);
|
||||
}
|
||||
|
||||
function getEmergencyAdmin() external override view returns (address) {
|
||||
return getAddress(EMERGENCY_ADMIN);
|
||||
}
|
||||
|
||||
function setEmergencyAdmin(address emergencyAdmin) external override onlyOwner {
|
||||
_addresses[EMERGENCY_ADMIN] = emergencyAdmin;
|
||||
emit EmergencyAdminUpdated(emergencyAdmin);
|
||||
}
|
||||
|
||||
function getPriceOracle() external override view returns (address) {
|
||||
|
|
|
@ -97,7 +97,7 @@ contract ATokensAndRatesHelper is Ownable {
|
|||
require(liquidationBonuses.length == tokens.length);
|
||||
|
||||
for (uint256 i = 0; i < tokens.length; i++) {
|
||||
LendingPoolConfigurator(poolConfigurator).enableReserveAsCollateral(
|
||||
LendingPoolConfigurator(poolConfigurator).configureReserveAsCollateral(
|
||||
tokens[i],
|
||||
baseLTVs[i],
|
||||
liquidationThresholds[i],
|
||||
|
|
|
@ -4,6 +4,7 @@ pragma solidity ^0.6.8;
|
|||
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
|
||||
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
|
||||
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||
import {ILendingPoolAddressesProvider} from './ILendingPoolAddressesProvider.sol';
|
||||
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
|
@ -32,13 +33,6 @@ interface ILendingPool {
|
|||
**/
|
||||
event Withdraw(address indexed reserve, address indexed user, address indexed to, uint256 amount);
|
||||
|
||||
event BorrowAllowanceDelegated(
|
||||
address indexed fromUser,
|
||||
address indexed toUser,
|
||||
address[] assets,
|
||||
uint256[] interestRateModes,
|
||||
uint256[] amounts
|
||||
);
|
||||
/**
|
||||
* @dev emitted on borrow
|
||||
* @param reserve the address of the reserve
|
||||
|
@ -195,27 +189,6 @@ interface ILendingPool {
|
|||
address to
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @dev Sets allowance to borrow on a certain type of debt assets for a certain user address
|
||||
* @param assets The underlying asset of each debt token
|
||||
* @param user The user to give allowance to
|
||||
* @param interestRateModes Types of debt: 1 for stable, 2 for variable
|
||||
* @param amounts Allowance amounts to borrow
|
||||
**/
|
||||
function delegateBorrowAllowance(
|
||||
address[] calldata assets,
|
||||
address user,
|
||||
uint256[] calldata interestRateModes,
|
||||
uint256[] calldata amounts
|
||||
) external;
|
||||
|
||||
function getBorrowAllowance(
|
||||
address fromUser,
|
||||
address toUser,
|
||||
address asset,
|
||||
uint256 interestRateMode
|
||||
) external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower
|
||||
* already deposited enough collateral.
|
||||
|
@ -368,6 +341,8 @@ interface ILendingPool {
|
|||
|
||||
function getReservesList() external view returns (address[] memory);
|
||||
|
||||
function getAddressesProvider() external view returns (ILendingPoolAddressesProvider);
|
||||
|
||||
/**
|
||||
* @dev Set the _pause state
|
||||
* @param val the boolean value to set the current pause state of LendingPool
|
||||
|
|
|
@ -8,7 +8,8 @@ pragma solidity ^0.6.8;
|
|||
|
||||
interface ILendingPoolAddressesProvider {
|
||||
event LendingPoolUpdated(address indexed newAddress);
|
||||
event AaveAdminUpdated(address indexed newAddress);
|
||||
event ConfigurationAdminUpdated(address indexed newAddress);
|
||||
event EmergencyAdminUpdated(address indexed newAddress);
|
||||
event LendingPoolConfiguratorUpdated(address indexed newAddress);
|
||||
event LendingPoolCollateralManagerUpdated(address indexed newAddress);
|
||||
event EthereumAddressUpdated(address indexed newAddress);
|
||||
|
@ -37,9 +38,13 @@ interface ILendingPoolAddressesProvider {
|
|||
|
||||
function setLendingPoolCollateralManager(address manager) external;
|
||||
|
||||
function getAaveAdmin() external view returns (address);
|
||||
function getPoolAdmin() external view returns (address);
|
||||
|
||||
function setAaveAdmin(address aaveAdmin) external;
|
||||
function setPoolAdmin(address admin) external;
|
||||
|
||||
function getEmergencyAdmin() external view returns (address);
|
||||
|
||||
function setEmergencyAdmin(address admin) external;
|
||||
|
||||
function getPriceOracle() external view returns (address);
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
* - The contract must not be paused.
|
||||
*/
|
||||
function _whenNotPaused() internal view {
|
||||
require(!_paused, Errors.P_IS_PAUSED);
|
||||
require(!_paused, Errors.LP_IS_PAUSED);
|
||||
}
|
||||
|
||||
function getRevision() internal override pure returns (uint256) {
|
||||
|
@ -107,6 +107,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
if (isFirstDeposit) {
|
||||
_usersConfig[onBehalfOf].setUsingAsCollateral(reserve.id, true);
|
||||
emit ReserveUsedAsCollateralEnabled(asset, onBehalfOf);
|
||||
}
|
||||
|
||||
//transfer to the aToken contract
|
||||
|
@ -157,6 +158,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
if (amountToWithdraw == userBalance) {
|
||||
_usersConfig[msg.sender].setUsingAsCollateral(reserve.id, false);
|
||||
emit ReserveUsedAsCollateralDisabled(asset, msg.sender);
|
||||
}
|
||||
|
||||
IAToken(aToken).burn(msg.sender, to, amountToWithdraw, reserve.liquidityIndex);
|
||||
|
@ -164,53 +166,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
emit Withdraw(asset, msg.sender, to, amountToWithdraw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev returns the borrow allowance of the user
|
||||
* @param asset The underlying asset of the debt token
|
||||
* @param fromUser The user to giving allowance
|
||||
* @param toUser The user to give allowance to
|
||||
* @param interestRateMode Type of debt: 1 for stable, 2 for variable
|
||||
* @return the current allowance of toUser
|
||||
**/
|
||||
function getBorrowAllowance(
|
||||
address fromUser,
|
||||
address toUser,
|
||||
address asset,
|
||||
uint256 interestRateMode
|
||||
) external override view returns (uint256) {
|
||||
return
|
||||
_borrowAllowance[_reserves[asset].getDebtTokenAddress(interestRateMode)][fromUser][toUser];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets allowance to borrow on a certain type of debt assets for a certain user address
|
||||
* @param assets The underlying asset of each debt token
|
||||
* @param user The user to give allowance to
|
||||
* @param interestRateModes Types of debt: 1 for stable, 2 for variable
|
||||
* @param amounts Allowance amounts to borrow
|
||||
**/
|
||||
function delegateBorrowAllowance(
|
||||
address[] calldata assets,
|
||||
address user,
|
||||
uint256[] calldata interestRateModes,
|
||||
uint256[] calldata amounts
|
||||
) external override {
|
||||
_whenNotPaused();
|
||||
|
||||
uint256 countAssets = assets.length;
|
||||
require(
|
||||
countAssets == interestRateModes.length && countAssets == amounts.length,
|
||||
Errors.LP_INCONSISTENT_PARAMS_LENGTH
|
||||
);
|
||||
|
||||
for (uint256 i = 0; i < countAssets; i++) {
|
||||
address debtToken = _reserves[assets[i]].getDebtTokenAddress(interestRateModes[i]);
|
||||
_borrowAllowance[debtToken][msg.sender][user] = amounts[i];
|
||||
}
|
||||
|
||||
emit BorrowAllowanceDelegated(msg.sender, user, assets, interestRateModes, amounts);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower
|
||||
* already deposited enough collateral.
|
||||
|
@ -230,15 +185,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
_whenNotPaused();
|
||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||
|
||||
if (onBehalfOf != msg.sender) {
|
||||
address debtToken = reserve.getDebtTokenAddress(interestRateMode);
|
||||
|
||||
_borrowAllowance[debtToken][onBehalfOf][msg
|
||||
.sender] = _borrowAllowance[debtToken][onBehalfOf][msg.sender].sub(
|
||||
amount,
|
||||
Errors.LP_BORROW_ALLOWANCE_ARE_NOT_ENOUGH
|
||||
);
|
||||
}
|
||||
_executeBorrow(
|
||||
ExecuteBorrowParams(
|
||||
asset,
|
||||
|
@ -345,6 +291,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
//burn stable rate tokens, mint variable rate tokens
|
||||
IStableDebtToken(reserve.stableDebtTokenAddress).burn(msg.sender, stableDebt);
|
||||
IVariableDebtToken(reserve.variableDebtTokenAddress).mint(
|
||||
msg.sender,
|
||||
msg.sender,
|
||||
stableDebt,
|
||||
reserve.variableBorrowIndex
|
||||
|
@ -357,6 +304,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
reserve.variableBorrowIndex
|
||||
);
|
||||
IStableDebtToken(reserve.stableDebtTokenAddress).mint(
|
||||
msg.sender,
|
||||
msg.sender,
|
||||
variableDebt,
|
||||
reserve.currentStableBorrowRate
|
||||
|
@ -418,6 +366,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
|
||||
IStableDebtToken(address(stableDebtToken)).burn(user, stableBorrowBalance);
|
||||
IStableDebtToken(address(stableDebtToken)).mint(
|
||||
user,
|
||||
user,
|
||||
stableBorrowBalance,
|
||||
reserve.currentStableBorrowRate
|
||||
|
@ -581,14 +530,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
vars.currentAmountPlusPremium
|
||||
);
|
||||
} else {
|
||||
if (msg.sender != onBehalfOf) {
|
||||
vars.debtToken = _reserves[vars.currentAsset].getDebtTokenAddress(modes[vars.i]);
|
||||
|
||||
_borrowAllowance[vars.debtToken][onBehalfOf][msg.sender] = _borrowAllowance[vars
|
||||
.debtToken][onBehalfOf][msg.sender]
|
||||
.sub(vars.currentAmount, Errors.LP_BORROW_ALLOWANCE_ARE_NOT_ENOUGH);
|
||||
}
|
||||
|
||||
//if the user didn't choose to return the funds, the system checks if there
|
||||
//is enough collateral and eventually open a position
|
||||
_executeBorrow(
|
||||
|
@ -753,7 +694,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
/**
|
||||
* @dev returns the addresses provider
|
||||
**/
|
||||
function getAddressesProvider() external view returns (ILendingPoolAddressesProvider) {
|
||||
function getAddressesProvider() external override view returns (ILendingPoolAddressesProvider) {
|
||||
return _addressesProvider;
|
||||
}
|
||||
|
||||
|
@ -793,11 +734,13 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
if (balanceFromBefore.sub(amount) == 0) {
|
||||
UserConfiguration.Map storage fromConfig = _usersConfig[from];
|
||||
fromConfig.setUsingAsCollateral(reserveId, false);
|
||||
emit ReserveUsedAsCollateralDisabled(asset, from);
|
||||
}
|
||||
|
||||
if (balanceToBefore == 0 && amount != 0) {
|
||||
UserConfiguration.Map storage toConfig = _usersConfig[to];
|
||||
toConfig.setUsingAsCollateral(reserveId, true);
|
||||
emit ReserveUsedAsCollateralEnabled(asset, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -923,12 +866,14 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
|||
currentStableRate = reserve.currentStableBorrowRate;
|
||||
|
||||
isFirstBorrowing = IStableDebtToken(reserve.stableDebtTokenAddress).mint(
|
||||
vars.user,
|
||||
vars.onBehalfOf,
|
||||
vars.amount,
|
||||
currentStableRate
|
||||
);
|
||||
} else {
|
||||
isFirstBorrowing = IVariableDebtToken(reserve.variableDebtTokenAddress).mint(
|
||||
vars.user,
|
||||
vars.onBehalfOf,
|
||||
vars.amount,
|
||||
reserve.variableBorrowIndex
|
||||
|
|
|
@ -13,6 +13,7 @@ import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
|||
import {ITokenConfiguration} from '../tokenization/interfaces/ITokenConfiguration.sol';
|
||||
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
|
||||
import {Errors} from '../libraries/helpers/Errors.sol';
|
||||
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
|
||||
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||
|
||||
/**
|
||||
|
@ -56,25 +57,19 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
event BorrowingDisabledOnReserve(address indexed asset);
|
||||
|
||||
/**
|
||||
* @dev emitted when a reserve is enabled as collateral.
|
||||
* @dev emitted when a a reserve collateralization risk parameters are updated.
|
||||
* @param asset the address of the reserve
|
||||
* @param ltv the loan to value of the asset when used as collateral
|
||||
* @param liquidationThreshold the threshold at which loans using this asset as collateral will be considered undercollateralized
|
||||
* @param liquidationBonus the bonus liquidators receive to liquidate this asset
|
||||
**/
|
||||
event ReserveEnabledAsCollateral(
|
||||
event CollateralConfigurationChanged(
|
||||
address indexed asset,
|
||||
uint256 ltv,
|
||||
uint256 liquidationThreshold,
|
||||
uint256 liquidationBonus
|
||||
);
|
||||
|
||||
/**
|
||||
* @dev emitted when a reserve is disabled as collateral
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
event ReserveDisabledAsCollateral(address indexed asset);
|
||||
|
||||
/**
|
||||
* @dev emitted when stable rate borrowing is enabled on a reserve
|
||||
* @param asset the address of the reserve
|
||||
|
@ -100,16 +95,16 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
event ReserveDeactivated(address indexed asset);
|
||||
|
||||
/**
|
||||
* @dev emitted when a reserve is freezed
|
||||
* @dev emitted when a reserve is frozen
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
event ReserveFreezed(address indexed asset);
|
||||
event ReserveFrozen(address indexed asset);
|
||||
|
||||
/**
|
||||
* @dev emitted when a reserve is unfreezed
|
||||
* @dev emitted when a reserve is unfrozen
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
event ReserveUnfreezed(address indexed asset);
|
||||
event ReserveUnfrozen(address indexed asset);
|
||||
|
||||
/**
|
||||
* @dev emitted when a reserve loan to value is updated
|
||||
|
@ -193,10 +188,21 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
ILendingPool internal pool;
|
||||
|
||||
/**
|
||||
* @dev only the lending pool manager can call functions affected by this modifier
|
||||
* @dev only the pool admin can call functions affected by this modifier
|
||||
**/
|
||||
modifier onlyAaveAdmin {
|
||||
require(addressesProvider.getAaveAdmin() == msg.sender, Errors.LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
modifier onlyPoolAdmin {
|
||||
require(addressesProvider.getPoolAdmin() == msg.sender, Errors.CALLER_NOT_POOL_ADMIN);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev only the emergency admin can call functions affected by this modifier
|
||||
**/
|
||||
modifier onlyEmergencyAdmin {
|
||||
require(
|
||||
addressesProvider.getEmergencyAdmin() == msg.sender,
|
||||
Errors.LPC_CALLER_NOT_EMERGENCY_ADMIN
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
|
@ -225,7 +231,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
address variableDebtTokenImpl,
|
||||
uint8 underlyingAssetDecimals,
|
||||
address interestRateStrategyAddress
|
||||
) public onlyAaveAdmin {
|
||||
) public onlyPoolAdmin {
|
||||
address asset = ITokenConfiguration(aTokenImpl).UNDERLYING_ASSET_ADDRESS();
|
||||
|
||||
require(
|
||||
|
@ -292,7 +298,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param asset the address of the reserve to be updated
|
||||
* @param implementation the address of the new aToken implementation
|
||||
**/
|
||||
function updateAToken(address asset, address implementation) external onlyAaveAdmin {
|
||||
function updateAToken(address asset, address implementation) external onlyPoolAdmin {
|
||||
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
|
||||
|
||||
_upgradeTokenImplementation(asset, reserveData.aTokenAddress, implementation);
|
||||
|
@ -305,7 +311,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param asset the address of the reserve to be updated
|
||||
* @param implementation the address of the new aToken implementation
|
||||
**/
|
||||
function updateStableDebtToken(address asset, address implementation) external onlyAaveAdmin {
|
||||
function updateStableDebtToken(address asset, address implementation) external onlyPoolAdmin {
|
||||
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
|
||||
|
||||
_upgradeTokenImplementation(asset, reserveData.stableDebtTokenAddress, implementation);
|
||||
|
@ -318,7 +324,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param asset the address of the reserve to be updated
|
||||
* @param implementation the address of the new aToken implementation
|
||||
**/
|
||||
function updateVariableDebtToken(address asset, address implementation) external onlyAaveAdmin {
|
||||
function updateVariableDebtToken(address asset, address implementation) external onlyPoolAdmin {
|
||||
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
|
||||
|
||||
_upgradeTokenImplementation(asset, reserveData.variableDebtTokenAddress, implementation);
|
||||
|
@ -333,7 +339,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
**/
|
||||
function enableBorrowingOnReserve(address asset, bool stableBorrowRateEnabled)
|
||||
external
|
||||
onlyAaveAdmin
|
||||
onlyPoolAdmin
|
||||
{
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
|
@ -349,7 +355,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @dev disables borrowing on a reserve
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
function disableBorrowingOnReserve(address asset) external onlyAaveAdmin {
|
||||
function disableBorrowingOnReserve(address asset) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setBorrowingEnabled(false);
|
||||
|
@ -359,48 +365,54 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev enables a reserve to be used as collateral
|
||||
* @dev configures the reserve collateralization parameters
|
||||
* @param asset the address of the reserve
|
||||
* @param ltv the loan to value of the asset when used as collateral
|
||||
* @param liquidationThreshold the threshold at which loans using this asset as collateral will be considered undercollateralized
|
||||
* @param liquidationBonus the bonus liquidators receive to liquidate this asset
|
||||
**/
|
||||
function enableReserveAsCollateral(
|
||||
function configureReserveAsCollateral(
|
||||
address asset,
|
||||
uint256 ltv,
|
||||
uint256 liquidationThreshold,
|
||||
uint256 liquidationBonus
|
||||
) external onlyAaveAdmin {
|
||||
) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
//validation of the parameters: the LTV can
|
||||
//only be lower or equal than the liquidation threshold
|
||||
//(otherwise a loan against the asset would cause instantaneous liquidation)
|
||||
require(ltv <= liquidationThreshold, Errors.LPC_INVALID_CONFIGURATION);
|
||||
|
||||
if (liquidationThreshold != 0) {
|
||||
//liquidation bonus must be bigger than 100.00%, otherwise the liquidator would receive less
|
||||
//collateral than needed to cover the debt
|
||||
require(
|
||||
liquidationBonus > PercentageMath.PERCENTAGE_FACTOR,
|
||||
Errors.LPC_INVALID_CONFIGURATION
|
||||
);
|
||||
} else {
|
||||
require(liquidationBonus == 0, Errors.LPC_INVALID_CONFIGURATION);
|
||||
//if the liquidation threshold is being set to 0,
|
||||
// the reserve is being disabled as collateral. To do so,
|
||||
//we need to ensure no liquidity is deposited
|
||||
_checkNoLiquidity(asset);
|
||||
}
|
||||
|
||||
currentConfig.setLtv(ltv);
|
||||
currentConfig.setLiquidationThreshold(liquidationThreshold);
|
||||
currentConfig.setLiquidationBonus(liquidationBonus);
|
||||
|
||||
pool.setConfiguration(asset, currentConfig.data);
|
||||
|
||||
emit ReserveEnabledAsCollateral(asset, ltv, liquidationThreshold, liquidationBonus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev disables a reserve as collateral
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
function disableReserveAsCollateral(address asset) external onlyAaveAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setLtv(0);
|
||||
|
||||
pool.setConfiguration(asset, currentConfig.data);
|
||||
|
||||
emit ReserveDisabledAsCollateral(asset);
|
||||
emit CollateralConfigurationChanged(asset, ltv, liquidationThreshold, liquidationBonus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev enable stable rate borrowing on a reserve
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
function enableReserveStableRate(address asset) external onlyAaveAdmin {
|
||||
function enableReserveStableRate(address asset) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setStableRateBorrowingEnabled(true);
|
||||
|
@ -414,7 +426,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @dev disable stable rate borrowing on a reserve
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
function disableReserveStableRate(address asset) external onlyAaveAdmin {
|
||||
function disableReserveStableRate(address asset) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setStableRateBorrowingEnabled(false);
|
||||
|
@ -428,7 +440,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @dev activates a reserve
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
function activateReserve(address asset) external onlyAaveAdmin {
|
||||
function activateReserve(address asset) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setActive(true);
|
||||
|
@ -442,15 +454,8 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @dev deactivates a reserve
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
function deactivateReserve(address asset) external onlyAaveAdmin {
|
||||
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
|
||||
|
||||
uint256 availableLiquidity = IERC20Detailed(asset).balanceOf(reserveData.aTokenAddress);
|
||||
|
||||
require(
|
||||
availableLiquidity == 0 && reserveData.currentLiquidityRate == 0,
|
||||
Errors.LPC_RESERVE_LIQUIDITY_NOT_0
|
||||
);
|
||||
function deactivateReserve(address asset) external onlyPoolAdmin {
|
||||
_checkNoLiquidity(asset);
|
||||
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
|
@ -462,31 +467,31 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev freezes a reserve. A freezed reserve doesn't accept any new deposit, borrow or rate swap, but can accept repayments, liquidations, rate rebalances and redeems
|
||||
* @dev freezes a reserve. A frozen reserve doesn't accept any new deposit, borrow or rate swap, but can accept repayments, liquidations, rate rebalances and redeems
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
function freezeReserve(address asset) external onlyAaveAdmin {
|
||||
function freezeReserve(address asset) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setFrozen(true);
|
||||
|
||||
pool.setConfiguration(asset, currentConfig.data);
|
||||
|
||||
emit ReserveFreezed(asset);
|
||||
emit ReserveFrozen(asset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev unfreezes a reserve
|
||||
* @param asset the address of the reserve
|
||||
**/
|
||||
function unfreezeReserve(address asset) external onlyAaveAdmin {
|
||||
function unfreezeReserve(address asset) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setFrozen(false);
|
||||
|
||||
pool.setConfiguration(asset, currentConfig.data);
|
||||
|
||||
emit ReserveUnfreezed(asset);
|
||||
emit ReserveUnfrozen(asset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -494,7 +499,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param asset the address of the reserve
|
||||
* @param ltv the new value for the loan to value
|
||||
**/
|
||||
function setLtv(address asset, uint256 ltv) external onlyAaveAdmin {
|
||||
function setLtv(address asset, uint256 ltv) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setLtv(ltv);
|
||||
|
@ -509,7 +514,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param asset the address of the reserve
|
||||
* @param reserveFactor the new reserve factor of the reserve
|
||||
**/
|
||||
function setReserveFactor(address asset, uint256 reserveFactor) external onlyAaveAdmin {
|
||||
function setReserveFactor(address asset, uint256 reserveFactor) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setReserveFactor(reserveFactor);
|
||||
|
@ -524,7 +529,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param asset the address of the reserve
|
||||
* @param threshold the new value for the liquidation threshold
|
||||
**/
|
||||
function setLiquidationThreshold(address asset, uint256 threshold) external onlyAaveAdmin {
|
||||
function setLiquidationThreshold(address asset, uint256 threshold) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setLiquidationThreshold(threshold);
|
||||
|
@ -539,7 +544,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param asset the address of the reserve
|
||||
* @param bonus the new value for the liquidation bonus
|
||||
**/
|
||||
function setLiquidationBonus(address asset, uint256 bonus) external onlyAaveAdmin {
|
||||
function setLiquidationBonus(address asset, uint256 bonus) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setLiquidationBonus(bonus);
|
||||
|
@ -554,7 +559,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @param asset the address of the reserve
|
||||
* @param decimals the new number of decimals
|
||||
**/
|
||||
function setReserveDecimals(address asset, uint256 decimals) external onlyAaveAdmin {
|
||||
function setReserveDecimals(address asset, uint256 decimals) external onlyPoolAdmin {
|
||||
ReserveConfiguration.Map memory currentConfig = pool.getConfiguration(asset);
|
||||
|
||||
currentConfig.setDecimals(decimals);
|
||||
|
@ -571,7 +576,7 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
**/
|
||||
function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress)
|
||||
external
|
||||
onlyAaveAdmin
|
||||
onlyPoolAdmin
|
||||
{
|
||||
pool.setReserveInterestRateStrategyAddress(asset, rateStrategyAddress);
|
||||
emit ReserveInterestRateStrategyChanged(asset, rateStrategyAddress);
|
||||
|
@ -626,7 +631,18 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
|||
* @dev pauses or unpauses LendingPool actions
|
||||
* @param val the boolean value to set the current pause state of LendingPool
|
||||
**/
|
||||
function setPoolPause(bool val) external onlyAaveAdmin {
|
||||
function setPoolPause(bool val) external onlyEmergencyAdmin {
|
||||
pool.setPause(val);
|
||||
}
|
||||
|
||||
function _checkNoLiquidity(address asset) internal view {
|
||||
ReserveLogic.ReserveData memory reserveData = pool.getReserveData(asset);
|
||||
|
||||
uint256 availableLiquidity = IERC20Detailed(asset).balanceOf(reserveData.aTokenAddress);
|
||||
|
||||
require(
|
||||
availableLiquidity == 0 && reserveData.currentLiquidityRate == 0,
|
||||
Errors.LPC_RESERVE_LIQUIDITY_NOT_0
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,14 +15,11 @@ contract LendingPoolStorage {
|
|||
|
||||
mapping(address => ReserveLogic.ReserveData) internal _reserves;
|
||||
mapping(address => UserConfiguration.Map) internal _usersConfig;
|
||||
// debt token address => user who gives allowance => user who receives allowance => amount
|
||||
mapping(address => mapping(address => mapping(address => uint256))) internal _borrowAllowance;
|
||||
|
||||
// the list of the available reserves, structured as a mapping for gas savings reasons
|
||||
mapping(uint256 => address) internal _reservesList;
|
||||
|
||||
uint256 internal _reservesCount;
|
||||
|
||||
bool internal _flashLiquidationLocked;
|
||||
bool internal _paused;
|
||||
}
|
||||
|
|
|
@ -259,7 +259,7 @@ library ReserveConfiguration {
|
|||
/**
|
||||
* @dev gets the configuration flags of the reserve
|
||||
* @param self the reserve configuration
|
||||
* @return the state flags representing active, freezed, borrowing enabled, stableRateBorrowing enabled
|
||||
* @return the state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled
|
||||
**/
|
||||
function getFlags(ReserveConfiguration.Map storage self)
|
||||
internal
|
||||
|
@ -336,7 +336,7 @@ library ReserveConfiguration {
|
|||
/**
|
||||
* @dev gets the configuration flags of the reserve from a memory object
|
||||
* @param self the reserve configuration
|
||||
* @return the state flags representing active, freezed, borrowing enabled, stableRateBorrowing enabled
|
||||
* @return the state flags representing active, frozen, borrowing enabled, stableRateBorrowing enabled
|
||||
**/
|
||||
function getFlagsMemory(ReserveConfiguration.Map memory self)
|
||||
internal
|
||||
|
|
|
@ -17,9 +17,14 @@ pragma solidity ^0.6.8;
|
|||
* - P = Pausable
|
||||
*/
|
||||
library Errors {
|
||||
//common errors
|
||||
string public constant CALLER_NOT_POOL_ADMIN = '33'; // 'The caller must be the pool admin'
|
||||
string public constant BORROW_ALLOWANCE_NOT_ENOUGH = '59'; // User borrows on behalf, but allowance are too small
|
||||
|
||||
//contract specific errors
|
||||
string public constant VL_AMOUNT_NOT_GREATER_THAN_0 = '1'; // 'Amount must be greater than 0'
|
||||
string public constant VL_NO_ACTIVE_RESERVE = '2'; // 'Action requires an active reserve'
|
||||
string public constant VL_NO_UNFREEZED_RESERVE = '3'; // 'Action requires an unfreezed reserve'
|
||||
string public constant VL_RESERVE_FROZEN = '3'; // 'Action cannot be performed because the reserve is frozen'
|
||||
string public constant VL_CURRENT_AVAILABLE_LIQUIDITY_NOT_ENOUGH = '4'; // 'The current liquidity is not enough'
|
||||
string public constant VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = '5'; // 'User cannot withdraw more than the available balance'
|
||||
string public constant VL_TRANSFER_NOT_ALLOWED = '6'; // 'Transfer cannot be allowed.'
|
||||
|
@ -29,7 +34,7 @@ library Errors {
|
|||
string public constant VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '10'; // 'Health factor is lesser than the liquidation threshold'
|
||||
string public constant VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = '11'; // 'There is not enough collateral to cover a new borrow'
|
||||
string public constant VL_STABLE_BORROWING_NOT_ENABLED = '12'; // stable borrowing not enabled
|
||||
string public constant VL_CALLATERAL_SAME_AS_BORROWING_CURRENCY = '13'; // collateral is (mostly) the same currency that is being borrowed
|
||||
string public constant VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY = '13'; // collateral is (mostly) the same currency that is being borrowed
|
||||
string public constant VL_AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = '14'; // 'The requested amount is greater than the max loan size in stable rate mode
|
||||
string public constant VL_NO_DEBT_OF_SELECTED_TYPE = '15'; // 'for repayment of stable debt, the user needs to have stable debt, otherwise, he needs to have variable debt'
|
||||
string public constant VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = '16'; // 'To repay on behalf of an user an explicit amount to repay is needed'
|
||||
|
@ -43,13 +48,12 @@ library Errors {
|
|||
string public constant LP_NOT_ENOUGH_LIQUIDITY_TO_BORROW = '24'; // 'There is not enough liquidity available to borrow'
|
||||
string public constant LP_REQUESTED_AMOUNT_TOO_SMALL = '25'; // 'The requested amount is too small for a FlashLoan.'
|
||||
string public constant LP_INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26'; // 'The actual balance of the protocol is inconsistent'
|
||||
string public constant LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27'; // 'The actual balance of the protocol is inconsistent'
|
||||
string public constant LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27'; // 'The caller of the function is not the lending pool configurator'
|
||||
string public constant LP_INCONSISTENT_FLASHLOAN_PARAMS = '28';
|
||||
string public constant AT_CALLER_MUST_BE_LENDING_POOL = '29'; // 'The caller of this function must be a lending pool'
|
||||
string public constant AT_CANNOT_GIVE_ALLVWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself'
|
||||
string public constant AT_TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero'
|
||||
string public constant RL_RESERVE_ALREADY_INITIALIZED = '32'; // 'Reserve has already been initialized'
|
||||
string public constant LPC_CALLER_NOT_AAVE_ADMIN = '33'; // 'The caller must be the aave admin'
|
||||
string public constant LPC_RESERVE_LIQUIDITY_NOT_0 = '34'; // 'The liquidity of the reserve needs to be 0'
|
||||
string public constant LPC_INVALID_ATOKEN_POOL_ADDRESS = '35'; // 'The liquidity of the reserve needs to be 0'
|
||||
string public constant LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = '36'; // 'The liquidity of the reserve needs to be 0'
|
||||
|
@ -57,6 +61,8 @@ library Errors {
|
|||
string public constant LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '38'; // 'The liquidity of the reserve needs to be 0'
|
||||
string public constant LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '39'; // 'The liquidity of the reserve needs to be 0'
|
||||
string public constant LPC_INVALID_ADDRESSES_PROVIDER_ID = '40'; // 'The liquidity of the reserve needs to be 0'
|
||||
string public constant LPC_INVALID_CONFIGURATION = '75'; // 'Invalid risk parameters for the reserve'
|
||||
string public constant LPC_CALLER_NOT_EMERGENCY_ADMIN = '76'; // 'The caller must be the emergency admin'
|
||||
string public constant LPAPR_PROVIDER_NOT_REGISTERED = '41'; // 'Provider is not registered'
|
||||
string public constant LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '42'; // 'Health factor is not below the threshold'
|
||||
string public constant LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = '43'; // 'The collateral chosen cannot be liquidated'
|
||||
|
@ -75,12 +81,11 @@ library Errors {
|
|||
string public constant AT_INVALID_MINT_AMOUNT = '56'; //invalid amount to mint
|
||||
string public constant LP_FAILED_REPAY_WITH_COLLATERAL = '57';
|
||||
string public constant AT_INVALID_BURN_AMOUNT = '58'; //invalid amount to burn
|
||||
string public constant LP_BORROW_ALLOWANCE_ARE_NOT_ENOUGH = '59'; // User borrows on behalf, but allowance are too small
|
||||
string public constant LP_FAILED_COLLATERAL_SWAP = '60';
|
||||
string public constant LP_INVALID_EQUAL_ASSETS_TO_SWAP = '61';
|
||||
string public constant LP_REENTRANCY_NOT_ALLOWED = '62';
|
||||
string public constant LP_CALLER_MUST_BE_AN_ATOKEN = '63';
|
||||
string public constant P_IS_PAUSED = '64'; // 'Pool is paused'
|
||||
string public constant LP_IS_PAUSED = '64'; // 'Pool is paused'
|
||||
string public constant LP_NO_MORE_RESERVES_ALLOWED = '65';
|
||||
string public constant LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = '66';
|
||||
string public constant RC_INVALID_LTV = '67';
|
||||
|
@ -102,6 +107,6 @@ library Errors {
|
|||
NO_ACTIVE_RESERVE,
|
||||
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
|
||||
INVALID_EQUAL_ASSETS_TO_SWAP,
|
||||
NO_UNFREEZED_RESERVE
|
||||
FROZEN_RESERVE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,4 +26,15 @@ library Helpers {
|
|||
DebtTokenBase(reserve.variableDebtTokenAddress).balanceOf(user)
|
||||
);
|
||||
}
|
||||
|
||||
function getUserCurrentDebtMemory(address user, ReserveLogic.ReserveData memory reserve)
|
||||
internal
|
||||
view
|
||||
returns (uint256, uint256)
|
||||
{
|
||||
return (
|
||||
DebtTokenBase(reserve.stableDebtTokenAddress).balanceOf(user),
|
||||
DebtTokenBase(reserve.variableDebtTokenAddress).balanceOf(user)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,28 +119,6 @@ library ReserveLogic {
|
|||
return cumulated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev returns an address of the debt token used for particular interest rate mode on asset.
|
||||
* @param reserve the reserve object
|
||||
* @param interestRateMode - STABLE or VARIABLE from ReserveLogic.InterestRateMode enum
|
||||
* @return an address of the corresponding debt token from reserve configuration
|
||||
**/
|
||||
function getDebtTokenAddress(ReserveLogic.ReserveData storage reserve, uint256 interestRateMode)
|
||||
external
|
||||
view
|
||||
returns (address)
|
||||
{
|
||||
require(
|
||||
ReserveLogic.InterestRateMode.STABLE == ReserveLogic.InterestRateMode(interestRateMode) ||
|
||||
ReserveLogic.InterestRateMode.VARIABLE == ReserveLogic.InterestRateMode(interestRateMode),
|
||||
Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED
|
||||
);
|
||||
return
|
||||
ReserveLogic.InterestRateMode.STABLE == ReserveLogic.InterestRateMode(interestRateMode)
|
||||
? reserve.stableDebtTokenAddress
|
||||
: reserve.variableDebtTokenAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Updates the liquidity cumulative index Ci and variable borrow cumulative index Bvc. Refer to the whitepaper for
|
||||
* a formal specification.
|
||||
|
|
|
@ -34,11 +34,11 @@ library ValidationLogic {
|
|||
* @param amount the amount to be deposited
|
||||
*/
|
||||
function validateDeposit(ReserveLogic.ReserveData storage reserve, uint256 amount) external view {
|
||||
(bool isActive, bool isFreezed, , ) = reserve.configuration.getFlags();
|
||||
(bool isActive, bool isFrozen, , ) = reserve.configuration.getFlags();
|
||||
|
||||
require(amount > 0, Errors.VL_AMOUNT_NOT_GREATER_THAN_0);
|
||||
require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
|
||||
require(!isFreezed, Errors.VL_NO_UNFREEZED_RESERVE);
|
||||
require(!isFrozen, Errors.VL_RESERVE_FROZEN);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,7 +97,7 @@ library ValidationLogic {
|
|||
ReserveLogic.InterestRateMode rateMode;
|
||||
bool healthFactorBelowThreshold;
|
||||
bool isActive;
|
||||
bool isFreezed;
|
||||
bool isFrozen;
|
||||
bool borrowingEnabled;
|
||||
bool stableRateBorrowingEnabled;
|
||||
}
|
||||
|
@ -133,15 +133,12 @@ library ValidationLogic {
|
|||
) external view {
|
||||
ValidateBorrowLocalVars memory vars;
|
||||
|
||||
(
|
||||
vars.isActive,
|
||||
vars.isFreezed,
|
||||
vars.borrowingEnabled,
|
||||
vars.stableRateBorrowingEnabled
|
||||
) = reserve.configuration.getFlags();
|
||||
(vars.isActive, vars.isFrozen, vars.borrowingEnabled, vars.stableRateBorrowingEnabled) = reserve
|
||||
.configuration
|
||||
.getFlags();
|
||||
|
||||
require(vars.isActive, Errors.VL_NO_ACTIVE_RESERVE);
|
||||
require(!vars.isFreezed, Errors.VL_NO_UNFREEZED_RESERVE);
|
||||
require(!vars.isFrozen, Errors.VL_RESERVE_FROZEN);
|
||||
|
||||
require(vars.borrowingEnabled, Errors.VL_BORROWING_NOT_ENABLED);
|
||||
|
||||
|
@ -202,7 +199,7 @@ library ValidationLogic {
|
|||
!userConfig.isUsingAsCollateral(reserve.id) ||
|
||||
reserve.configuration.getLtv() == 0 ||
|
||||
amount > IERC20(reserve.aTokenAddress).balanceOf(userAddress),
|
||||
Errors.VL_CALLATERAL_SAME_AS_BORROWING_CURRENCY
|
||||
Errors.VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY
|
||||
);
|
||||
|
||||
vars.availableLiquidity = IERC20(asset).balanceOf(reserve.aTokenAddress);
|
||||
|
@ -266,10 +263,10 @@ library ValidationLogic {
|
|||
uint256 variableDebt,
|
||||
ReserveLogic.InterestRateMode currentRateMode
|
||||
) external view {
|
||||
(bool isActive, bool isFreezed, , bool stableRateEnabled) = reserve.configuration.getFlags();
|
||||
(bool isActive, bool isFrozen, , bool stableRateEnabled) = reserve.configuration.getFlags();
|
||||
|
||||
require(isActive, Errors.VL_NO_ACTIVE_RESERVE);
|
||||
require(!isFreezed, Errors.VL_NO_UNFREEZED_RESERVE);
|
||||
require(!isFrozen, Errors.VL_RESERVE_FROZEN);
|
||||
|
||||
if (currentRateMode == ReserveLogic.InterestRateMode.STABLE) {
|
||||
require(stableDebt > 0, Errors.VL_NO_STABLE_RATE_LOAN_IN_RESERVE);
|
||||
|
@ -288,7 +285,7 @@ library ValidationLogic {
|
|||
!userConfig.isUsingAsCollateral(reserve.id) ||
|
||||
reserve.configuration.getLtv() == 0 ||
|
||||
stableDebt.add(variableDebt) > IERC20(reserve.aTokenAddress).balanceOf(msg.sender),
|
||||
Errors.VL_CALLATERAL_SAME_AS_BORROWING_CURRENCY
|
||||
Errors.VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY
|
||||
);
|
||||
} else {
|
||||
revert(Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED);
|
||||
|
|
|
@ -18,11 +18,13 @@ import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
|
|||
contract ChainlinkProxyPriceProvider is IPriceOracleGetter, Ownable {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
event WethSet(address indexed weth);
|
||||
event AssetSourceUpdated(address indexed asset, address indexed source);
|
||||
event FallbackOracleUpdated(address indexed fallbackOracle);
|
||||
|
||||
mapping(address => IChainlinkAggregator) private assetsSources;
|
||||
IPriceOracleGetter private _fallbackOracle;
|
||||
address public immutable WETH;
|
||||
|
||||
/// @notice Constructor
|
||||
/// @param assets The addresses of the assets
|
||||
|
@ -32,10 +34,13 @@ contract ChainlinkProxyPriceProvider is IPriceOracleGetter, Ownable {
|
|||
constructor(
|
||||
address[] memory assets,
|
||||
address[] memory sources,
|
||||
address fallbackOracle
|
||||
address fallbackOracle,
|
||||
address weth
|
||||
) public {
|
||||
_setFallbackOracle(fallbackOracle);
|
||||
_setAssetsSources(assets, sources);
|
||||
WETH = weth;
|
||||
emit WethSet(weth);
|
||||
}
|
||||
|
||||
/// @notice External function called by the Aave governance to set or replace sources of assets
|
||||
|
@ -77,8 +82,10 @@ contract ChainlinkProxyPriceProvider is IPriceOracleGetter, Ownable {
|
|||
/// @param asset The asset address
|
||||
function getAssetPrice(address asset) public override view returns (uint256) {
|
||||
IChainlinkAggregator source = assetsSources[asset];
|
||||
// If there is no registered source for the asset, call the fallbackOracle
|
||||
if (address(source) == address(0)) {
|
||||
|
||||
if (asset == WETH) {
|
||||
return 1 ether;
|
||||
} else if (address(source) == address(0)) {
|
||||
return _fallbackOracle.getAssetPrice(asset);
|
||||
} else {
|
||||
int256 price = IChainlinkAggregator(source).latestAnswer();
|
||||
|
|
163
contracts/misc/UiPoolDataProvider.sol
Normal file
163
contracts/misc/UiPoolDataProvider.sol
Normal file
|
@ -0,0 +1,163 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||
import {IUiPoolDataProvider} from './interfaces/IUiPoolDataProvider.sol';
|
||||
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
|
||||
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
|
||||
import {IAToken} from '../tokenization/interfaces/IAToken.sol';
|
||||
import {IVariableDebtToken} from '../tokenization/interfaces/IVariableDebtToken.sol';
|
||||
import {IStableDebtToken} from '../tokenization/interfaces/IStableDebtToken.sol';
|
||||
|
||||
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
|
||||
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
|
||||
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
|
||||
import {
|
||||
DefaultReserveInterestRateStrategy
|
||||
} from '../lendingpool/DefaultReserveInterestRateStrategy.sol';
|
||||
|
||||
contract UiPoolDataProvider is IUiPoolDataProvider {
|
||||
using WadRayMath for uint256;
|
||||
using ReserveConfiguration for ReserveConfiguration.Map;
|
||||
using UserConfiguration for UserConfiguration.Map;
|
||||
|
||||
address public constant MOCK_USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96;
|
||||
|
||||
function getInterestRateStrategySlopes(DefaultReserveInterestRateStrategy interestRateStrategy)
|
||||
internal
|
||||
view
|
||||
returns (
|
||||
uint256,
|
||||
uint256,
|
||||
uint256,
|
||||
uint256
|
||||
)
|
||||
{
|
||||
return (
|
||||
interestRateStrategy.variableRateSlope1(),
|
||||
interestRateStrategy.variableRateSlope2(),
|
||||
interestRateStrategy.stableRateSlope1(),
|
||||
interestRateStrategy.stableRateSlope2()
|
||||
);
|
||||
}
|
||||
|
||||
function getReservesData(ILendingPoolAddressesProvider provider, address user)
|
||||
external
|
||||
override
|
||||
view
|
||||
returns (
|
||||
AggregatedReserveData[] memory,
|
||||
UserReserveData[] memory,
|
||||
uint256
|
||||
)
|
||||
{
|
||||
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
|
||||
IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle());
|
||||
address[] memory reserves = lendingPool.getReservesList();
|
||||
UserConfiguration.Map memory userConfig = lendingPool.getUserConfiguration(user);
|
||||
|
||||
AggregatedReserveData[] memory reservesData = new AggregatedReserveData[](reserves.length);
|
||||
UserReserveData[] memory userReservesData = new UserReserveData[](
|
||||
user != address(0) ? reserves.length : 0
|
||||
);
|
||||
|
||||
for (uint256 i = 0; i < reserves.length; i++) {
|
||||
AggregatedReserveData memory reserveData = reservesData[i];
|
||||
reserveData.underlyingAsset = reserves[i];
|
||||
|
||||
// reserve current state
|
||||
ReserveLogic.ReserveData memory baseData = lendingPool.getReserveData(
|
||||
reserveData.underlyingAsset
|
||||
);
|
||||
reserveData.liquidityIndex = baseData.liquidityIndex;
|
||||
reserveData.variableBorrowIndex = baseData.variableBorrowIndex;
|
||||
reserveData.liquidityRate = baseData.currentLiquidityRate;
|
||||
reserveData.variableBorrowRate = baseData.currentVariableBorrowRate;
|
||||
reserveData.stableBorrowRate = baseData.currentStableBorrowRate;
|
||||
reserveData.lastUpdateTimestamp = baseData.lastUpdateTimestamp;
|
||||
reserveData.aTokenAddress = baseData.aTokenAddress;
|
||||
reserveData.stableDebtTokenAddress = baseData.stableDebtTokenAddress;
|
||||
reserveData.variableDebtTokenAddress = baseData.variableDebtTokenAddress;
|
||||
reserveData.interestRateStrategyAddress = baseData.interestRateStrategyAddress;
|
||||
reserveData.priceInEth = oracle.getAssetPrice(reserveData.underlyingAsset);
|
||||
|
||||
reserveData.availableLiquidity = IERC20Detailed(reserveData.underlyingAsset).balanceOf(
|
||||
reserveData.aTokenAddress
|
||||
);
|
||||
(
|
||||
reserveData.totalPrincipalStableDebt,
|
||||
,
|
||||
reserveData.averageStableRate,
|
||||
reserveData.stableDebtLastUpdateTimestamp
|
||||
) = IStableDebtToken(reserveData.stableDebtTokenAddress).getSupplyData();
|
||||
reserveData.totalScaledVariableDebt = IVariableDebtToken(reserveData.variableDebtTokenAddress)
|
||||
.scaledTotalSupply();
|
||||
|
||||
// reserve configuration
|
||||
|
||||
// we're getting this info from the aToken, because some of assets can be not compliant with ETC20Detailed
|
||||
reserveData.symbol = IERC20Detailed(reserveData.aTokenAddress).symbol();
|
||||
reserveData.name = '';
|
||||
|
||||
(
|
||||
reserveData.baseLTVasCollateral,
|
||||
reserveData.reserveLiquidationThreshold,
|
||||
reserveData.reserveLiquidationBonus,
|
||||
reserveData.decimals,
|
||||
reserveData.reserveFactor
|
||||
) = baseData.configuration.getParamsMemory();
|
||||
(
|
||||
reserveData.isActive,
|
||||
reserveData.isFrozen,
|
||||
reserveData.borrowingEnabled,
|
||||
reserveData.stableBorrowRateEnabled
|
||||
) = baseData.configuration.getFlagsMemory();
|
||||
reserveData.usageAsCollateralEnabled = reserveData.baseLTVasCollateral != 0;
|
||||
(
|
||||
reserveData.variableRateSlope1,
|
||||
reserveData.variableRateSlope2,
|
||||
reserveData.stableRateSlope1,
|
||||
reserveData.stableRateSlope2
|
||||
) = getInterestRateStrategySlopes(
|
||||
DefaultReserveInterestRateStrategy(reserveData.interestRateStrategyAddress)
|
||||
);
|
||||
|
||||
if (user != address(0)) {
|
||||
// user reserve data
|
||||
userReservesData[i].underlyingAsset = reserveData.underlyingAsset;
|
||||
userReservesData[i].scaledATokenBalance = IAToken(reserveData.aTokenAddress)
|
||||
.scaledBalanceOf(user);
|
||||
userReservesData[i].usageAsCollateralEnabledOnUser = userConfig.isUsingAsCollateral(i);
|
||||
|
||||
if (userConfig.isBorrowing(i)) {
|
||||
userReservesData[i].scaledVariableDebt = IVariableDebtToken(
|
||||
reserveData
|
||||
.variableDebtTokenAddress
|
||||
)
|
||||
.scaledBalanceOf(user);
|
||||
userReservesData[i].principalStableDebt = IStableDebtToken(
|
||||
reserveData
|
||||
.stableDebtTokenAddress
|
||||
)
|
||||
.principalBalanceOf(user);
|
||||
if (userReservesData[i].principalStableDebt != 0) {
|
||||
userReservesData[i].stableBorrowRate = IStableDebtToken(
|
||||
reserveData
|
||||
.stableDebtTokenAddress
|
||||
)
|
||||
.getUserStableRate(user);
|
||||
userReservesData[i].stableBorrowLastUpdateTimestamp = IStableDebtToken(
|
||||
reserveData
|
||||
.stableDebtTokenAddress
|
||||
)
|
||||
.getUserLastUpdated(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS));
|
||||
}
|
||||
}
|
184
contracts/misc/WETHGateway.sol
Normal file
184
contracts/misc/WETHGateway.sol
Normal file
|
@ -0,0 +1,184 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {IWETH} from './interfaces/IWETH.sol';
|
||||
import {IWETHGateway} from './interfaces/IWETHGateway.sol';
|
||||
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||
import {IAToken} from '../tokenization/interfaces/IAToken.sol';
|
||||
import {ReserveLogic} from '../libraries/logic/ReserveLogic.sol';
|
||||
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
|
||||
import {UserConfiguration} from '../libraries/configuration/UserConfiguration.sol';
|
||||
import {Helpers} from '../libraries/helpers/Helpers.sol';
|
||||
import {Ownable} from '../dependencies/openzeppelin/contracts/Ownable.sol';
|
||||
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||
|
||||
contract WETHGateway is IWETHGateway, Ownable {
|
||||
using ReserveConfiguration for ReserveConfiguration.Map;
|
||||
using UserConfiguration for UserConfiguration.Map;
|
||||
|
||||
IWETH internal immutable WETH;
|
||||
ILendingPool internal immutable POOL;
|
||||
IAToken internal immutable aWETH;
|
||||
|
||||
/**
|
||||
* @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool.
|
||||
* @param weth Address of the Wrapped Ether contract
|
||||
* @param pool Address of the LendingPool contract
|
||||
**/
|
||||
constructor(address weth, address pool) public {
|
||||
ILendingPool poolInstance = ILendingPool(pool);
|
||||
WETH = IWETH(weth);
|
||||
POOL = poolInstance;
|
||||
aWETH = IAToken(poolInstance.getReserveData(weth).aTokenAddress);
|
||||
IWETH(weth).approve(pool, uint256(-1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens)
|
||||
* is minted.
|
||||
* @param onBehalfOf address of the user who will receive the aTokens representing the deposit
|
||||
* @param referralCode integrators are assigned a referral code and can potentially receive rewards.
|
||||
**/
|
||||
function depositETH(address onBehalfOf, uint16 referralCode) external override payable {
|
||||
WETH.deposit{value: msg.value}();
|
||||
POOL.deposit(address(WETH), msg.value, onBehalfOf, referralCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev withdraws the WETH _reserves of msg.sender.
|
||||
* @param amount amount of aWETH to withdraw and receive native ETH
|
||||
* @param to address of the user who will receive native ETH
|
||||
*/
|
||||
function withdrawETH(uint256 amount, address to) external override {
|
||||
uint256 userBalance = aWETH.balanceOf(msg.sender);
|
||||
uint256 amountToWithdraw = amount;
|
||||
|
||||
// if amount is equal to uint(-1), the user wants to redeem everything
|
||||
if (amount == type(uint256).max) {
|
||||
amountToWithdraw = userBalance;
|
||||
}
|
||||
aWETH.transferFrom(msg.sender, address(this), amountToWithdraw);
|
||||
POOL.withdraw(address(WETH), amountToWithdraw, address(this));
|
||||
WETH.withdraw(amountToWithdraw);
|
||||
_safeTransferETH(to, amountToWithdraw);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
|
||||
* @param amount the amount to repay, or uint256(-1) if the user wants to repay everything
|
||||
* @param rateMode the rate mode to repay
|
||||
* @param onBehalfOf the address for which msg.sender is repaying
|
||||
*/
|
||||
function repayETH(
|
||||
uint256 amount,
|
||||
uint256 rateMode,
|
||||
address onBehalfOf
|
||||
) external override payable {
|
||||
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebtMemory(
|
||||
onBehalfOf,
|
||||
POOL.getReserveData(address(WETH))
|
||||
);
|
||||
|
||||
uint256 paybackAmount = ReserveLogic.InterestRateMode(rateMode) ==
|
||||
ReserveLogic.InterestRateMode.STABLE
|
||||
? stableDebt
|
||||
: variableDebt;
|
||||
|
||||
if (amount < paybackAmount) {
|
||||
paybackAmount = amount;
|
||||
}
|
||||
require(msg.value >= paybackAmount, 'msg.value is less than repayment amount');
|
||||
WETH.deposit{value: paybackAmount}();
|
||||
POOL.repay(address(WETH), msg.value, rateMode, onBehalfOf);
|
||||
|
||||
// refund remaining dust eth
|
||||
if (msg.value > paybackAmount) _safeTransferETH(msg.sender, msg.value - paybackAmount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev borrow WETH, unwraps to ETH and send both the ETH and DebtTokens to msg.sender, via `approveDelegation` and onBehalf argument in `LendingPool.borrow`.
|
||||
* @param amount the amount of ETH to borrow
|
||||
* @param interesRateMode the interest rate mode
|
||||
* @param referralCode integrators are assigned a referral code and can potentially receive rewards
|
||||
*/
|
||||
function borrowETH(
|
||||
uint256 amount,
|
||||
uint256 interesRateMode,
|
||||
uint16 referralCode
|
||||
) external override {
|
||||
POOL.borrow(address(WETH), amount, interesRateMode, referralCode, msg.sender);
|
||||
WETH.withdraw(amount);
|
||||
_safeTransferETH(msg.sender, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev transfer ETH to an address, revert if it fails.
|
||||
* @param to recipient of the transfer
|
||||
* @param value the amount to send
|
||||
*/
|
||||
function _safeTransferETH(address to, uint256 value) internal {
|
||||
(bool success, ) = to.call{value: value}(new bytes(0));
|
||||
require(success, 'ETH_TRANSFER_FAILED');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev transfer ERC20 from the utility contract, for ERC20 recovery in case of stuck tokens due
|
||||
* direct transfers to the contract address.
|
||||
* @param token token to transfer
|
||||
* @param to recipient of the transfer
|
||||
* @param amount amount to send
|
||||
*/
|
||||
function emergencyTokenTransfer(
|
||||
address token,
|
||||
address to,
|
||||
uint256 amount
|
||||
) external onlyOwner {
|
||||
IERC20(token).transfer(to, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev transfer native Ether from the utility contract, for native Ether recovery in case of stuck Ether
|
||||
* due selfdestructs or transfer ether to pre-computated contract address before deployment.
|
||||
* @param to recipient of the transfer
|
||||
* @param amount amount to send
|
||||
*/
|
||||
function emergencyEtherTransfer(address to, uint256 amount) external onlyOwner {
|
||||
_safeTransferETH(to, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get WETH address used by WETHGateway
|
||||
*/
|
||||
function getWETHAddress() external view returns (address) {
|
||||
return address(WETH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get aWETH address used by WETHGateway
|
||||
*/
|
||||
function getAWETHAddress() external view returns (address) {
|
||||
return address(aWETH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get LendingPool address used by WETHGateway
|
||||
*/
|
||||
function getLendingPoolAddress() external view returns (address) {
|
||||
return address(POOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Only WETH contract is allowed to transfer ETH here. Prevent other addresses to send Ether to this contract.
|
||||
*/
|
||||
receive() external payable {
|
||||
require(msg.sender == address(WETH), 'Receive not allowed');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revert fallback calls
|
||||
*/
|
||||
fallback() external payable {
|
||||
revert('Fallback not allowed');
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ pragma experimental ABIEncoderV2;
|
|||
import {Address} from '../dependencies/openzeppelin/contracts/Address.sol';
|
||||
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
|
||||
|
||||
import {LendingPoolAddressesProvider} from '../configuration/LendingPoolAddressesProvider.sol';
|
||||
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
|
||||
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||
import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
|
||||
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
|
||||
|
@ -24,9 +24,10 @@ contract WalletBalanceProvider {
|
|||
using SafeERC20 for IERC20;
|
||||
using ReserveConfiguration for ReserveConfiguration.Map;
|
||||
|
||||
LendingPoolAddressesProvider internal immutable _provider;
|
||||
ILendingPoolAddressesProvider internal immutable _provider;
|
||||
address constant MOCK_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
|
||||
|
||||
constructor(LendingPoolAddressesProvider provider) public {
|
||||
constructor(ILendingPoolAddressesProvider provider) public {
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
|
@ -45,12 +46,13 @@ contract WalletBalanceProvider {
|
|||
- return 0 on non-contract address
|
||||
**/
|
||||
function balanceOf(address user, address token) public view returns (uint256) {
|
||||
// check if token is actually a contract
|
||||
if (token.isContract()) {
|
||||
if (token == MOCK_ETH_ADDRESS) {
|
||||
return user.balance; // ETH balance
|
||||
// check if token is actually a contract
|
||||
} else if (token.isContract()) {
|
||||
return IERC20(token).balanceOf(user);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
revert('INVALID_TOKEN');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,12 +70,7 @@ contract WalletBalanceProvider {
|
|||
|
||||
for (uint256 i = 0; i < users.length; i++) {
|
||||
for (uint256 j = 0; j < tokens.length; j++) {
|
||||
uint256 _offset = i * tokens.length;
|
||||
if (!tokens[j].isContract()) {
|
||||
revert('INVALID_TOKEN');
|
||||
} else {
|
||||
balances[_offset + j] = balanceOf(users[i], tokens[j]);
|
||||
}
|
||||
balances[i * tokens.length + j] = balanceOf(users[i], tokens[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,11 +88,16 @@ contract WalletBalanceProvider {
|
|||
ILendingPool pool = ILendingPool(_provider.getLendingPool());
|
||||
|
||||
address[] memory reserves = pool.getReservesList();
|
||||
address[] memory reservesWithEth = new address[](reserves.length + 1);
|
||||
for (uint256 i = 0; i < reserves.length; i++) {
|
||||
reservesWithEth[i] = reserves[i];
|
||||
}
|
||||
reservesWithEth[reserves.length] = MOCK_ETH_ADDRESS;
|
||||
|
||||
uint256[] memory balances = new uint256[](reserves.length);
|
||||
uint256[] memory balances = new uint256[](reservesWithEth.length);
|
||||
|
||||
for (uint256 j = 0; j < reserves.length; j++) {
|
||||
ReserveConfiguration.Map memory configuration = pool.getConfiguration(reserves[j]);
|
||||
ReserveConfiguration.Map memory configuration = pool.getConfiguration(reservesWithEth[j]);
|
||||
|
||||
(bool isActive, , , ) = configuration.getFlagsMemory();
|
||||
|
||||
|
@ -103,9 +105,10 @@ contract WalletBalanceProvider {
|
|||
balances[j] = 0;
|
||||
continue;
|
||||
}
|
||||
balances[j] = balanceOf(user, reserves[j]);
|
||||
balances[j] = balanceOf(user, reservesWithEth[j]);
|
||||
}
|
||||
balances[reservesWithEth.length] = balanceOf(user, MOCK_ETH_ADDRESS);
|
||||
|
||||
return (reserves, balances);
|
||||
return (reservesWithEth, balances);
|
||||
}
|
||||
}
|
||||
|
|
94
contracts/misc/interfaces/IUiPoolDataProvider.sol
Normal file
94
contracts/misc/interfaces/IUiPoolDataProvider.sol
Normal file
|
@ -0,0 +1,94 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
|
||||
import {ReserveLogic} from '../../libraries/logic/ReserveLogic.sol';
|
||||
|
||||
interface IUiPoolDataProvider {
|
||||
struct AggregatedReserveData {
|
||||
address underlyingAsset;
|
||||
string name;
|
||||
string symbol;
|
||||
uint256 decimals;
|
||||
uint256 baseLTVasCollateral;
|
||||
uint256 reserveLiquidationThreshold;
|
||||
uint256 reserveLiquidationBonus;
|
||||
uint256 reserveFactor;
|
||||
bool usageAsCollateralEnabled;
|
||||
bool borrowingEnabled;
|
||||
bool stableBorrowRateEnabled;
|
||||
bool isActive;
|
||||
bool isFrozen;
|
||||
// base data
|
||||
uint128 liquidityIndex;
|
||||
uint128 variableBorrowIndex;
|
||||
uint128 liquidityRate;
|
||||
uint128 variableBorrowRate;
|
||||
uint128 stableBorrowRate;
|
||||
uint40 lastUpdateTimestamp;
|
||||
address aTokenAddress;
|
||||
address stableDebtTokenAddress;
|
||||
address variableDebtTokenAddress;
|
||||
address interestRateStrategyAddress;
|
||||
//
|
||||
uint256 availableLiquidity;
|
||||
uint256 totalPrincipalStableDebt;
|
||||
uint256 averageStableRate;
|
||||
uint256 stableDebtLastUpdateTimestamp;
|
||||
uint256 totalScaledVariableDebt;
|
||||
uint256 priceInEth;
|
||||
uint256 variableRateSlope1;
|
||||
uint256 variableRateSlope2;
|
||||
uint256 stableRateSlope1;
|
||||
uint256 stableRateSlope2;
|
||||
}
|
||||
//
|
||||
// struct ReserveData {
|
||||
// uint256 averageStableBorrowRate;
|
||||
// uint256 totalLiquidity;
|
||||
// }
|
||||
|
||||
struct UserReserveData {
|
||||
address underlyingAsset;
|
||||
uint256 scaledATokenBalance;
|
||||
bool usageAsCollateralEnabledOnUser;
|
||||
uint256 stableBorrowRate;
|
||||
uint256 scaledVariableDebt;
|
||||
uint256 principalStableDebt;
|
||||
uint256 stableBorrowLastUpdateTimestamp;
|
||||
}
|
||||
|
||||
//
|
||||
// struct ATokenSupplyData {
|
||||
// string name;
|
||||
// string symbol;
|
||||
// uint8 decimals;
|
||||
// uint256 totalSupply;
|
||||
// address aTokenAddress;
|
||||
// }
|
||||
|
||||
function getReservesData(ILendingPoolAddressesProvider provider, address user)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
AggregatedReserveData[] memory,
|
||||
UserReserveData[] memory,
|
||||
uint256
|
||||
);
|
||||
|
||||
// function getUserReservesData(ILendingPoolAddressesProvider provider, address user)
|
||||
// external
|
||||
// view
|
||||
// returns (UserReserveData[] memory);
|
||||
//
|
||||
// function getAllATokenSupply(ILendingPoolAddressesProvider provider)
|
||||
// external
|
||||
// view
|
||||
// returns (ATokenSupplyData[] memory);
|
||||
//
|
||||
// function getATokenSupply(address[] calldata aTokens)
|
||||
// external
|
||||
// view
|
||||
// returns (ATokenSupplyData[] memory);
|
||||
}
|
16
contracts/misc/interfaces/IWETH.sol
Normal file
16
contracts/misc/interfaces/IWETH.sol
Normal file
|
@ -0,0 +1,16 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
|
||||
interface IWETH {
|
||||
function deposit() external payable;
|
||||
|
||||
function withdraw(uint256) external;
|
||||
|
||||
function approve(address guy, uint256 wad) external returns (bool);
|
||||
|
||||
function transferFrom(
|
||||
address src,
|
||||
address dst,
|
||||
uint256 wad
|
||||
) external returns (bool);
|
||||
}
|
20
contracts/misc/interfaces/IWETHGateway.sol
Normal file
20
contracts/misc/interfaces/IWETHGateway.sol
Normal file
|
@ -0,0 +1,20 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
|
||||
interface IWETHGateway {
|
||||
function depositETH(address onBehalfOf, uint16 referralCode) external payable;
|
||||
|
||||
function withdrawETH(uint256 amount, address onBehalfOf) external;
|
||||
|
||||
function repayETH(
|
||||
uint256 amount,
|
||||
uint256 rateMode,
|
||||
address onBehalfOf
|
||||
) external payable;
|
||||
|
||||
function borrowETH(
|
||||
uint256 amount,
|
||||
uint256 interesRateMode,
|
||||
uint16 referralCode
|
||||
) external;
|
||||
}
|
8
contracts/mocks/attacks/SefldestructTransfer.sol
Normal file
8
contracts/mocks/attacks/SefldestructTransfer.sol
Normal file
|
@ -0,0 +1,8 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
|
||||
contract SelfdestructTransfer {
|
||||
function destroyAndTransfer(address payable to) external payable {
|
||||
selfdestruct(to);
|
||||
}
|
||||
}
|
758
contracts/mocks/dependencies/weth/WETH9.sol
Normal file
758
contracts/mocks/dependencies/weth/WETH9.sol
Normal file
|
@ -0,0 +1,758 @@
|
|||
// Copyright (C) 2015, 2016, 2017 Dapphub
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
pragma solidity >=0.4.22 <=0.6.8;
|
||||
|
||||
contract WETH9 {
|
||||
string public name = 'Wrapped Ether';
|
||||
string public symbol = 'WETH';
|
||||
uint8 public decimals = 18;
|
||||
|
||||
event Approval(address indexed src, address indexed guy, uint256 wad);
|
||||
event Transfer(address indexed src, address indexed dst, uint256 wad);
|
||||
event Deposit(address indexed dst, uint256 wad);
|
||||
event Withdrawal(address indexed src, uint256 wad);
|
||||
|
||||
mapping(address => uint256) public balanceOf;
|
||||
mapping(address => mapping(address => uint256)) public allowance;
|
||||
|
||||
receive() external payable {
|
||||
deposit();
|
||||
}
|
||||
|
||||
function deposit() public payable {
|
||||
balanceOf[msg.sender] += msg.value;
|
||||
emit Deposit(msg.sender, msg.value);
|
||||
}
|
||||
|
||||
function withdraw(uint256 wad) public {
|
||||
require(balanceOf[msg.sender] >= wad);
|
||||
balanceOf[msg.sender] -= wad;
|
||||
msg.sender.transfer(wad);
|
||||
emit Withdrawal(msg.sender, wad);
|
||||
}
|
||||
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return address(this).balance;
|
||||
}
|
||||
|
||||
function approve(address guy, uint256 wad) public returns (bool) {
|
||||
allowance[msg.sender][guy] = wad;
|
||||
emit Approval(msg.sender, guy, wad);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transfer(address dst, uint256 wad) public returns (bool) {
|
||||
return transferFrom(msg.sender, dst, wad);
|
||||
}
|
||||
|
||||
function transferFrom(
|
||||
address src,
|
||||
address dst,
|
||||
uint256 wad
|
||||
) public returns (bool) {
|
||||
require(balanceOf[src] >= wad);
|
||||
|
||||
if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) {
|
||||
require(allowance[src][msg.sender] >= wad);
|
||||
allowance[src][msg.sender] -= wad;
|
||||
}
|
||||
|
||||
balanceOf[src] -= wad;
|
||||
balanceOf[dst] += wad;
|
||||
|
||||
emit Transfer(src, dst, wad);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
*/
|
|
@ -72,7 +72,6 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
|
|||
? _amountToApprove
|
||||
: amounts[i].add(premiums[i]);
|
||||
//execution does not fail - mint tokens and return them to the _destination
|
||||
//note: if the reserve is eth, the mock contract must receive at least _fee ETH before calling executeOperation
|
||||
|
||||
token.mint(premiums[i]);
|
||||
|
||||
|
|
34
contracts/mocks/tokens/MintableDelegationERC20.sol
Normal file
34
contracts/mocks/tokens/MintableDelegationERC20.sol
Normal file
|
@ -0,0 +1,34 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
|
||||
import {ERC20} from '../../dependencies/openzeppelin/contracts/ERC20.sol';
|
||||
|
||||
/**
|
||||
* @title ERC20Mintable
|
||||
* @dev ERC20 minting logic
|
||||
*/
|
||||
contract MintableDelegationERC20 is ERC20 {
|
||||
address public delegatee;
|
||||
|
||||
constructor(
|
||||
string memory name,
|
||||
string memory symbol,
|
||||
uint8 decimals
|
||||
) public ERC20(name, symbol) {
|
||||
_setupDecimals(decimals);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Function to mint tokensp
|
||||
* @param value The amount of tokens to mint.
|
||||
* @return A boolean that indicates if the operation was successful.
|
||||
*/
|
||||
function mint(uint256 value) public returns (bool) {
|
||||
_mint(msg.sender, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function delegate(address delegateeAddress) external {
|
||||
delegatee = delegateeAddress;
|
||||
}
|
||||
}
|
11
contracts/mocks/tokens/WETH9Mocked.sol
Normal file
11
contracts/mocks/tokens/WETH9Mocked.sol
Normal file
|
@ -0,0 +1,11 @@
|
|||
pragma solidity >=0.4.22 <=0.6.8;
|
||||
|
||||
import {WETH9} from '../dependencies/weth/WETH9.sol';
|
||||
|
||||
contract WETH9Mocked is WETH9 {
|
||||
// Mint not backed by Ether: only for testing purposes
|
||||
function mint(uint256 value) public returns (bool) {
|
||||
balanceOf[msg.sender] += value;
|
||||
emit Transfer(address(0), msg.sender, value);
|
||||
}
|
||||
}
|
|
@ -13,7 +13,7 @@ import {SafeERC20} from '../dependencies/openzeppelin/contracts/SafeERC20.sol';
|
|||
/**
|
||||
* @title Aave ERC20 AToken
|
||||
*
|
||||
* @dev Implementation of the interest bearing token for the DLP protocol.
|
||||
* @dev Implementation of the interest bearing token for the Aave protocol.
|
||||
* @author Aave
|
||||
*/
|
||||
contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
||||
|
@ -108,7 +108,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
|||
|
||||
//transfer event to track balances
|
||||
emit Transfer(user, address(0), amount);
|
||||
emit Burn(_msgSender(), receiverOfUnderlying, amount, index);
|
||||
emit Burn(user, receiverOfUnderlying, amount, index);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
72
contracts/tokenization/DelegationAwareAToken.sol
Normal file
72
contracts/tokenization/DelegationAwareAToken.sol
Normal file
|
@ -0,0 +1,72 @@
|
|||
// SPDX-License-Identifier: agpl-3.0
|
||||
pragma solidity ^0.6.8;
|
||||
|
||||
import {AToken} from './AToken.sol';
|
||||
import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||
import {Errors} from '../libraries/helpers/Errors.sol';
|
||||
|
||||
/**
|
||||
* @title IDelegationToken
|
||||
* @dev implements an interface for tokens that have a delegation function
|
||||
**/
|
||||
interface IDelegationToken {
|
||||
function delegate(address delegatee) external;
|
||||
}
|
||||
|
||||
/**
|
||||
* @title Aave AToken with delegation capabilities
|
||||
*
|
||||
* @dev Implementation of the interest bearing token for the Aave protocol. This version of the aToken
|
||||
* adds a function which gives the Aave protocol the ability to delegate voting power of the underlying asset.
|
||||
* The underlying asset needs to be compatible with the COMP delegation interface
|
||||
* @author Aave
|
||||
*/
|
||||
contract DelegationAwareAToken is AToken {
|
||||
/**
|
||||
* @dev only the aave admin can call this function
|
||||
**/
|
||||
modifier onlyPoolAdmin {
|
||||
require(
|
||||
_msgSender() == ILendingPool(POOL).getAddressesProvider().getPoolAdmin(),
|
||||
Errors.CALLER_NOT_POOL_ADMIN
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(
|
||||
ILendingPool pool,
|
||||
address underlyingAssetAddress,
|
||||
address reserveTreasury,
|
||||
string memory tokenName,
|
||||
string memory tokenSymbol,
|
||||
address incentivesController
|
||||
)
|
||||
public
|
||||
AToken(
|
||||
pool,
|
||||
underlyingAssetAddress,
|
||||
reserveTreasury,
|
||||
tokenName,
|
||||
tokenSymbol,
|
||||
incentivesController
|
||||
)
|
||||
{}
|
||||
|
||||
function initialize(
|
||||
uint8 _underlyingAssetDecimals,
|
||||
string calldata _tokenName,
|
||||
string calldata _tokenSymbol
|
||||
) external virtual override initializer {
|
||||
_setName(_tokenName);
|
||||
_setSymbol(_tokenSymbol);
|
||||
_setDecimals(_underlyingAssetDecimals);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev delegates voting power of the underlying asset to a specific address
|
||||
* @param delegatee the address that will receive the delegation
|
||||
**/
|
||||
function delegateUnderlyingTo(address delegatee) external onlyPoolAdmin {
|
||||
IDelegationToken(UNDERLYING_ASSET_ADDRESS).delegate(delegatee);
|
||||
}
|
||||
}
|
|
@ -16,9 +16,10 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
|
||||
uint256 public constant DEBT_TOKEN_REVISION = 0x1;
|
||||
|
||||
uint256 private _avgStableRate;
|
||||
mapping(address => uint40) _timestamps;
|
||||
uint40 _totalSupplyTimestamp;
|
||||
uint256 internal _avgStableRate;
|
||||
mapping(address => uint40) internal _timestamps;
|
||||
mapping(address => uint256) internal _usersData;
|
||||
uint40 internal _totalSupplyTimestamp;
|
||||
|
||||
constructor(
|
||||
address pool,
|
||||
|
@ -95,17 +96,18 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
**/
|
||||
function mint(
|
||||
address user,
|
||||
address onBehalfOf,
|
||||
uint256 amount,
|
||||
uint256 rate
|
||||
) external override onlyLendingPool returns (bool) {
|
||||
MintLocalVars memory vars;
|
||||
|
||||
if (user != onBehalfOf) {
|
||||
_decreaseBorrowAllowance(onBehalfOf, user, amount);
|
||||
}
|
||||
|
||||
//cumulates the user debt
|
||||
(
|
||||
uint256 previousBalance,
|
||||
uint256 currentBalance,
|
||||
uint256 balanceIncrease
|
||||
) = _calculateBalanceIncrease(user);
|
||||
(, uint256 currentBalance, uint256 balanceIncrease) = _calculateBalanceIncrease(onBehalfOf);
|
||||
|
||||
//accrueing the interest accumulation to the stored total supply and caching it
|
||||
vars.previousSupply = totalSupply();
|
||||
|
@ -115,17 +117,17 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
vars.amountInRay = amount.wadToRay();
|
||||
|
||||
//calculates the new stable rate for the user
|
||||
vars.newStableRate = _usersData[user]
|
||||
vars.newStableRate = _usersData[onBehalfOf]
|
||||
.rayMul(currentBalance.wadToRay())
|
||||
.add(vars.amountInRay.rayMul(rate))
|
||||
.rayDiv(currentBalance.add(amount).wadToRay());
|
||||
|
||||
require(vars.newStableRate < (1 << 128), 'Debt token: stable rate overflow');
|
||||
_usersData[user] = vars.newStableRate;
|
||||
_usersData[onBehalfOf] = vars.newStableRate;
|
||||
|
||||
//updating the user and supply timestamp
|
||||
//solium-disable-next-line
|
||||
_totalSupplyTimestamp = _timestamps[user] = uint40(block.timestamp);
|
||||
_totalSupplyTimestamp = _timestamps[onBehalfOf] = uint40(block.timestamp);
|
||||
|
||||
//calculates the updated average stable rate
|
||||
vars.currentAvgStableRate = _avgStableRate = vars
|
||||
|
@ -134,19 +136,20 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
.add(rate.rayMul(vars.amountInRay))
|
||||
.rayDiv(vars.nextSupply.wadToRay());
|
||||
|
||||
_mint(user, amount.add(balanceIncrease), vars.previousSupply);
|
||||
_mint(onBehalfOf, amount.add(balanceIncrease), vars.previousSupply);
|
||||
|
||||
// transfer event to track balances
|
||||
emit Transfer(address(0), user, amount);
|
||||
emit Transfer(address(0), onBehalfOf, amount);
|
||||
|
||||
emit Mint(
|
||||
user,
|
||||
onBehalfOf,
|
||||
amount,
|
||||
previousBalance,
|
||||
currentBalance,
|
||||
balanceIncrease,
|
||||
vars.newStableRate,
|
||||
vars.currentAvgStableRate
|
||||
vars.currentAvgStableRate,
|
||||
vars.nextSupply
|
||||
);
|
||||
|
||||
return currentBalance == 0;
|
||||
|
@ -158,24 +161,21 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
* @param amount the amount of debt tokens to mint
|
||||
**/
|
||||
function burn(address user, uint256 amount) external override onlyLendingPool {
|
||||
(
|
||||
uint256 previousBalance,
|
||||
uint256 currentBalance,
|
||||
uint256 balanceIncrease
|
||||
) = _calculateBalanceIncrease(user);
|
||||
(, uint256 currentBalance, uint256 balanceIncrease) = _calculateBalanceIncrease(user);
|
||||
|
||||
uint256 previousSupply = totalSupply();
|
||||
uint256 newStableRate = 0;
|
||||
uint256 nextSupply = 0;
|
||||
|
||||
//since the total supply and each single user debt accrue separately,
|
||||
//there might be accumulation errors so that the last borrower repaying
|
||||
//might actually try to repay more than the available debt supply.
|
||||
//in this case we simply set the total supply and the avg stable rate to 0
|
||||
if (previousSupply <= amount) {
|
||||
newStableRate = _avgStableRate = 0;
|
||||
_avgStableRate = 0;
|
||||
_totalSupply = 0;
|
||||
} else {
|
||||
uint256 nextSupply = _totalSupply = previousSupply.sub(amount);
|
||||
nextSupply = _totalSupply = previousSupply.sub(amount);
|
||||
newStableRate = _avgStableRate = _avgStableRate
|
||||
.rayMul(previousSupply.wadToRay())
|
||||
.sub(_usersData[user].rayMul(amount.wadToRay()))
|
||||
|
@ -201,7 +201,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
|
|||
// transfer event to track balances
|
||||
emit Transfer(user, address(0), amount);
|
||||
|
||||
emit Burn(user, amount, previousBalance, currentBalance, balanceIncrease, newStableRate);
|
||||
emit Burn(user, amount, currentBalance, balanceIncrease, newStableRate, nextSupply);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -55,17 +55,22 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
|
|||
**/
|
||||
function mint(
|
||||
address user,
|
||||
address onBehalfOf,
|
||||
uint256 amount,
|
||||
uint256 index
|
||||
) external override onlyLendingPool returns (bool) {
|
||||
uint256 previousBalance = super.balanceOf(user);
|
||||
if (user != onBehalfOf) {
|
||||
_decreaseBorrowAllowance(onBehalfOf, user, amount);
|
||||
}
|
||||
|
||||
uint256 previousBalance = super.balanceOf(onBehalfOf);
|
||||
uint256 amountScaled = amount.rayDiv(index);
|
||||
require(amountScaled != 0, Errors.AT_INVALID_MINT_AMOUNT);
|
||||
|
||||
_mint(user, amountScaled);
|
||||
_mint(onBehalfOf, amountScaled);
|
||||
|
||||
emit Transfer(address(0), user, amount);
|
||||
emit Mint(user, amount, index);
|
||||
emit Transfer(address(0), onBehalfOf, amount);
|
||||
emit Mint(user, onBehalfOf, amount, index);
|
||||
|
||||
return previousBalance == 0;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,17 @@ import {Errors} from '../../libraries/helpers/Errors.sol';
|
|||
*/
|
||||
|
||||
abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
||||
event BorrowAllowanceDelegated(
|
||||
address indexed fromUser,
|
||||
address indexed toUser,
|
||||
address asset,
|
||||
uint256 amount
|
||||
);
|
||||
|
||||
address public immutable UNDERLYING_ASSET_ADDRESS;
|
||||
ILendingPool public immutable POOL;
|
||||
mapping(address => uint256) internal _usersData;
|
||||
|
||||
mapping(address => mapping(address => uint256)) internal _borrowAllowances;
|
||||
|
||||
/**
|
||||
* @dev Only lending pool can call functions marked by this modifier
|
||||
|
@ -58,6 +66,28 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
|||
_setDecimals(decimals);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 {
|
||||
_borrowAllowances[_msgSender()][delegatee] = amount;
|
||||
emit BorrowAllowanceDelegated(_msgSender(), delegatee, UNDERLYING_ASSET_ADDRESS, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
return _borrowAllowances[fromUser][toUser];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Being non transferrable, the debt token does not implement any of the
|
||||
* standard ERC20 functions for transfer and allowance.
|
||||
|
@ -118,4 +148,19 @@ abstract contract DebtTokenBase is IncentivizedERC20, VersionedInitializable {
|
|||
subtractedValue;
|
||||
revert('ALLOWANCE_NOT_SUPPORTED');
|
||||
}
|
||||
|
||||
function _decreaseBorrowAllowance(
|
||||
address delegator,
|
||||
address delegatee,
|
||||
uint256 amount
|
||||
) internal {
|
||||
uint256 newAllowance = _borrowAllowances[delegator][delegatee].sub(
|
||||
amount,
|
||||
Errors.BORROW_ALLOWANCE_NOT_ENOUGH
|
||||
);
|
||||
|
||||
_borrowAllowances[delegator][delegatee] = newAllowance;
|
||||
|
||||
emit BorrowAllowanceDelegated(delegator, delegatee, UNDERLYING_ASSET_ADDRESS, newAllowance);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,27 @@ import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
|
|||
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
|
||||
|
||||
interface IAToken is IERC20, IScaledBalanceToken {
|
||||
/**
|
||||
* @dev emitted after the mint action
|
||||
* @param from the address performing the mint
|
||||
* @param value the amount to be minted
|
||||
* @param index the last index of the reserve
|
||||
**/
|
||||
event Mint(address indexed from, uint256 value, uint256 index);
|
||||
|
||||
/**
|
||||
* @dev mints aTokens to user
|
||||
* only lending pools can call this function
|
||||
* @param user the address receiving the minted tokens
|
||||
* @param amount the amount of tokens to mint
|
||||
* @param index the liquidity index
|
||||
*/
|
||||
function mint(
|
||||
address user,
|
||||
uint256 amount,
|
||||
uint256 index
|
||||
) external returns (bool);
|
||||
|
||||
/**
|
||||
* @dev emitted after aTokens are burned
|
||||
* @param from the address performing the redeem
|
||||
|
|
|
@ -2,27 +2,6 @@
|
|||
pragma solidity ^0.6.8;
|
||||
|
||||
interface IScaledBalanceToken {
|
||||
/**
|
||||
* @dev emitted after the mint action
|
||||
* @param from the address performing the mint
|
||||
* @param value the amount to be minted
|
||||
* @param index the last index of the reserve
|
||||
**/
|
||||
event Mint(address indexed from, uint256 value, uint256 index);
|
||||
|
||||
/**
|
||||
* @dev mints aTokens to user
|
||||
* only lending pools can call this function
|
||||
* @param user the address receiving the minted tokens
|
||||
* @param amount the amount of tokens to mint
|
||||
* @param index the liquidity index
|
||||
*/
|
||||
function mint(
|
||||
address user,
|
||||
uint256 amount,
|
||||
uint256 index
|
||||
) external returns (bool);
|
||||
|
||||
/**
|
||||
* @dev returns the principal balance of the user. The principal balance is the last
|
||||
* updated stored balance, which does not consider the perpetually accruing interest.
|
||||
|
|
|
@ -15,40 +15,42 @@ pragma solidity ^0.6.8;
|
|||
interface IStableDebtToken {
|
||||
/**
|
||||
* @dev emitted when new stable debt is minted
|
||||
* @param user the address of the user
|
||||
* @param user the address of the user who triggered the minting
|
||||
* @param onBehalfOf the address of the user
|
||||
* @param amount the amount minted
|
||||
* @param previousBalance the previous balance of the user
|
||||
* @param currentBalance the current balance of the user
|
||||
* @param balanceIncrease the debt increase since the last update
|
||||
* @param balanceIncrease the the increase in balance since the last action of the user
|
||||
* @param newRate the rate of the debt after the minting
|
||||
* @param avgStableRate the new average stable rate after the minting
|
||||
* @param newTotalSupply the new total supply of the stable debt token after the action
|
||||
**/
|
||||
event Mint(
|
||||
address indexed user,
|
||||
address indexed onBehalfOf,
|
||||
uint256 amount,
|
||||
uint256 previousBalance,
|
||||
uint256 currentBalance,
|
||||
uint256 balanceIncrease,
|
||||
uint256 newRate,
|
||||
uint256 avgStableRate
|
||||
uint256 avgStableRate,
|
||||
uint256 newTotalSupply
|
||||
);
|
||||
|
||||
/**
|
||||
* @dev emitted when new stable debt is burned
|
||||
* @param user the address of the user
|
||||
* @param amount the amount minted
|
||||
* @param previousBalance the previous balance of the user
|
||||
* @param currentBalance the current balance of the user
|
||||
* @param balanceIncrease the debt increase since the last update
|
||||
* @param balanceIncrease the the increase in balance since the last action of the user
|
||||
* @param avgStableRate the new average stable rate after the minting
|
||||
* @param newTotalSupply the new total supply of the stable debt token after the action
|
||||
**/
|
||||
event Burn(
|
||||
address indexed user,
|
||||
uint256 amount,
|
||||
uint256 previousBalance,
|
||||
uint256 currentBalance,
|
||||
uint256 balanceIncrease,
|
||||
uint256 avgStableRate
|
||||
uint256 avgStableRate,
|
||||
uint256 newTotalSupply
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -60,6 +62,7 @@ interface IStableDebtToken {
|
|||
**/
|
||||
function mint(
|
||||
address user,
|
||||
address onBehalfOf,
|
||||
uint256 amount,
|
||||
uint256 rate
|
||||
) external returns (bool);
|
||||
|
|
|
@ -9,6 +9,29 @@ import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
|
|||
* @notice defines the basic interface for a variable debt token.
|
||||
**/
|
||||
interface IVariableDebtToken is IScaledBalanceToken {
|
||||
/**
|
||||
* @dev emitted after the mint action
|
||||
* @param from the address performing the mint
|
||||
* @param onBehalfOf the address of the user on which behalf minting has been performed
|
||||
* @param value the amount to be minted
|
||||
* @param index the last index of the reserve
|
||||
**/
|
||||
event Mint(address indexed from, address indexed onBehalfOf, uint256 value, uint256 index);
|
||||
|
||||
/**
|
||||
* @dev mints aTokens to user
|
||||
* only lending pools can call this function
|
||||
* @param user the address receiving the minted tokens
|
||||
* @param amount the amount of tokens to mint
|
||||
* @param index the liquidity index
|
||||
*/
|
||||
function mint(
|
||||
address user,
|
||||
address onBehalfOf,
|
||||
uint256 amount,
|
||||
uint256 index
|
||||
) external returns (bool);
|
||||
|
||||
/**
|
||||
* @dev emitted when variable debt is burnt
|
||||
* @param user the user which debt has been burned
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
"loc": {"start": {"line": 82, "column": 2}, "end": {"line": 85, "column": 2}}
|
||||
},
|
||||
"7": {
|
||||
"name": "getAaveAdmin",
|
||||
"name": "getPoolAdmin",
|
||||
"line": 92,
|
||||
"loc": {"start": {"line": 92, "column": 2}, "end": {"line": 94, "column": 2}}
|
||||
},
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"MintableERC20": {
|
||||
"buidlerevm": {
|
||||
"address": "0x58F132FBB86E21545A4Bace3C19f1C05d86d7A22",
|
||||
"address": "0x18b9306737eaf6E8FC8e737F488a1AE077b18053",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x18b9306737eaf6E8FC8e737F488a1AE077b18053",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
|
@ -9,6 +13,10 @@
|
|||
"buidlerevm": {
|
||||
"address": "0x7c2C195CD6D34B8F845992d380aADB2730bB9C6F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x7c2C195CD6D34B8F845992d380aADB2730bB9C6F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LEND": {
|
||||
|
@ -21,249 +29,559 @@
|
|||
"buidlerevm": {
|
||||
"address": "0x0078371BDeDE8aAc7DeBfFf451B74c5EDB385Af7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x0078371BDeDE8aAc7DeBfFf451B74c5EDB385Af7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"BAT": {
|
||||
"buidlerevm": {
|
||||
"address": "0xf4e77E5Da47AC3125140c470c71cBca77B5c638c",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xf4e77E5Da47AC3125140c470c71cBca77B5c638c",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"WETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0xf784709d2317D872237C4bC22f867d1BAe2913AB",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xf784709d2317D872237C4bC22f867d1BAe2913AB",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"USDC": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3619DbE27d7c1e7E91aA738697Ae7Bc5FC3eACA5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x3619DbE27d7c1e7E91aA738697Ae7Bc5FC3eACA5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"USDT": {
|
||||
"buidlerevm": {
|
||||
"address": "0x038B86d9d8FAFdd0a02ebd1A476432877b0107C8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x038B86d9d8FAFdd0a02ebd1A476432877b0107C8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"SUSD": {
|
||||
"buidlerevm": {
|
||||
"address": "0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ZRX": {
|
||||
"buidlerevm": {
|
||||
"address": "0x500D1d6A4c7D8Ae28240b47c8FCde034D827fD5e",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x500D1d6A4c7D8Ae28240b47c8FCde034D827fD5e",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MKR": {
|
||||
"buidlerevm": {
|
||||
"address": "0xc4905364b78a742ccce7B890A89514061E47068D",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xc4905364b78a742ccce7B890A89514061E47068D",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"WBTC": {
|
||||
"buidlerevm": {
|
||||
"address": "0xD6C850aeBFDC46D7F4c207e445cC0d6B0919BDBe",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xD6C850aeBFDC46D7F4c207e445cC0d6B0919BDBe",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LINK": {
|
||||
"buidlerevm": {
|
||||
"address": "0x8B5B7a6055E54a36fF574bbE40cf2eA68d5554b3",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x8B5B7a6055E54a36fF574bbE40cf2eA68d5554b3",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"KNC": {
|
||||
"buidlerevm": {
|
||||
"address": "0xEcc0a6dbC0bb4D51E4F84A315a9e5B0438cAD4f0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xEcc0a6dbC0bb4D51E4F84A315a9e5B0438cAD4f0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MANA": {
|
||||
"buidlerevm": {
|
||||
"address": "0x20Ce94F404343aD2752A2D01b43fa407db9E0D00",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x20Ce94F404343aD2752A2D01b43fa407db9E0D00",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"REP": {
|
||||
"buidlerevm": {
|
||||
"address": "0x1d80315fac6aBd3EfeEbE97dEc44461ba7556160",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x1d80315fac6aBd3EfeEbE97dEc44461ba7556160",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"SNX": {
|
||||
"buidlerevm": {
|
||||
"address": "0x2D8553F9ddA85A9B3259F6Bf26911364B85556F5",
|
||||
"address": "0x52d3b94181f8654db2530b0fEe1B19173f519C52",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x52d3b94181f8654db2530b0fEe1B19173f519C52",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"BUSD": {
|
||||
"buidlerevm": {
|
||||
"address": "0x52d3b94181f8654db2530b0fEe1B19173f519C52",
|
||||
"address": "0xd15468525c35BDBC1eD8F2e09A00F8a173437f2f",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xd15468525c35BDBC1eD8F2e09A00F8a173437f2f",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"USD": {
|
||||
"buidlerevm": {
|
||||
"address": "0xd15468525c35BDBC1eD8F2e09A00F8a173437f2f",
|
||||
"address": "0x7e35Eaf7e8FBd7887ad538D4A38Df5BbD073814a",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x7e35Eaf7e8FBd7887ad538D4A38Df5BbD073814a",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_DAI_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x7e35Eaf7e8FBd7887ad538D4A38Df5BbD073814a",
|
||||
"address": "0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_USDC_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x5bcb88A0d20426e451332eE6C4324b0e663c50E0",
|
||||
"address": "0x58F132FBB86E21545A4Bace3C19f1C05d86d7A22",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x58F132FBB86E21545A4Bace3C19f1C05d86d7A22",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_SETH_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3521eF8AaB0323004A6dD8b03CE890F4Ea3A13f5",
|
||||
"address": "0xa4bcDF64Cdd5451b6ac3743B414124A6299B65FF",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xa4bcDF64Cdd5451b6ac3743B414124A6299B65FF",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_LINK_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x53369fd4680FfE3DfF39Fc6DDa9CfbfD43daeA2E",
|
||||
"address": "0x22474D350EC2dA53D717E30b96e9a2B7628Ede5b",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x22474D350EC2dA53D717E30b96e9a2B7628Ede5b",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_MKR_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0xB00cC45B4a7d3e1FEE684cFc4417998A1c183e6d",
|
||||
"address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI_LEND_ETH": {
|
||||
"buidlerevm": {
|
||||
"address": "0x58F132FBB86E21545A4Bace3C19f1C05d86d7A22",
|
||||
"address": "0x18b9306737eaf6E8FC8e737F488a1AE077b18053",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x18b9306737eaf6E8FC8e737F488a1AE077b18053",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LendingPoolAddressesProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0xa4bcDF64Cdd5451b6ac3743B414124A6299B65FF",
|
||||
"address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x688C81eC2A0Be6F287fD8C9c343D299c03A34804",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xFAe0fd738dAbc8a0426F47437322b6d026A9FD95",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LendingPoolAddressesProviderRegistry": {
|
||||
"buidlerevm": {
|
||||
"address": "0x5A0773Ff307Bf7C71a832dBB5312237fD3437f9F",
|
||||
"address": "0x18b9306737eaf6E8FC8e737F488a1AE077b18053",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xf189cC1eD07cEFB6e61082104e12673E133163f5",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x8456161947DFc1fC159A0B26c025cD2b4bba0c3e",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ReserveLogic": {
|
||||
"buidlerevm": {
|
||||
"address": "0x78Ee8Fb9fE5abD5e347Fc94c2fb85596d1f60e3c",
|
||||
"address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x757855037B01c45832f8d662D217C766Ba4e8e74",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x5F6CaC05CDF893f029b29F44d368eAeD40e573B6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"GenericLogic": {
|
||||
"buidlerevm": {
|
||||
"address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7",
|
||||
"address": "0xA4765Ff72A9F3CfE73089bb2c3a41B838DF71574",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xBc013D1412E0F4acacAa64CDc1c93e8A3Ecd8fF4",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x92cfBAB5A86631e9F1A6126b42E01A74eadA61Df",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ValidationLogic": {
|
||||
"buidlerevm": {
|
||||
"address": "0xA4765Ff72A9F3CfE73089bb2c3a41B838DF71574",
|
||||
"address": "0x35c1419Da7cf0Ff885B8Ef8EA9242FEF6800c99b",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xba681EfB276237903df60ef92D564610A393Dbd6",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x78Aeff0658Fa67735fBF99Ce7CDB01Fe5D520259",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LendingPool": {
|
||||
"buidlerevm": {
|
||||
"address": "0x35c1419Da7cf0Ff885B8Ef8EA9242FEF6800c99b",
|
||||
"address": "0xe2607EabC87fd0A4856840bF23da8458cDF0434F",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x59525b17808F0a7eFe62303ca46e596A5a602683"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x813F07B2100e59ba6555d0D6dBA2660c68514665"
|
||||
}
|
||||
},
|
||||
"LendingPoolConfigurator": {
|
||||
"buidlerevm": {
|
||||
"address": "0x6642B57e4265BAD868C17Fc1d1F4F88DBBA04Aa8"
|
||||
"address": "0xdbaA15927b1463EdD14Cf51D082BD7703Fd1C238"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x0a9bc0ce44e6473a1B0e30b54b7227de6E75Fd83"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xdbaA15927b1463EdD14Cf51D082BD7703Fd1C238"
|
||||
}
|
||||
},
|
||||
"StableAndVariableTokensHelper": {
|
||||
"buidlerevm": {
|
||||
"address": "0x0C6c3C47A1f650809B0D1048FDf9603e09473D7E",
|
||||
"address": "0x06bA8d8af0dF898D0712DffFb0f862cC51AF45c2",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x882AD7981FE3d63200A23F5d009A1d0488b5ea7e",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xE4C10Db67595aF2Cb4166c8C274e0140f7E43059",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ATokensAndRatesHelper": {
|
||||
"buidlerevm": {
|
||||
"address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7",
|
||||
"address": "0xA4765Ff72A9F3CfE73089bb2c3a41B838DF71574",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0x20Bfad73e3A8aA9161b5c553f7825002a175DB23",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x099d9fF8F818290C8b5B7Db5bFca84CEebd2714c",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"PriceOracle": {
|
||||
"buidlerevm": {
|
||||
"address": "0xb682dEEf4f8e298d86bFc3e21f50c675151FB974",
|
||||
"address": "0x1750499D05Ed1674d822430FB960d5F6731fDf64",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x85bdE212E66e2BAE510E44Ed59116c1eC712795b",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockAggregator": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3D8FFB457fedDFBc760F3F243283F52692b579B1",
|
||||
"address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x8Dd7f10813aC8fCB83ad7ad94e941D53b002fBc7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ChainlinkProxyPriceProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0xEC1C93A9f6a9e18E97784c76aC52053587FcDB89",
|
||||
"address": "0x7B6C3e5486D9e6959441ab554A889099eed76290",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xfA9dbd706c674801F50169f4B5862cCe045408E6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"LendingRateOracle": {
|
||||
"buidlerevm": {
|
||||
"address": "0xAF6BA11790D1942625C0c2dA07da19AB63845cfF",
|
||||
"address": "0xD83D2773a7873ae2b5f8Fb92097e20a8C64F691E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0xbFAD7C67855cc0272CC5ED00dAabeFDB31E7190a",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"AaveProtocolTestHelpers": {
|
||||
"buidlerevm": {
|
||||
"address": "0xf4830d6b1D70C8595d3BD8A63f9ed9F636DB9ef2"
|
||||
"address": "0x93472C0e03215F9c33DA240Eb16703C8244eAa8c"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xe875775D75F384944E77086Ea54bAD008ea8004A",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x93472C0e03215F9c33DA240Eb16703C8244eAa8c"
|
||||
}
|
||||
},
|
||||
"LendingPoolCollateralManager": {
|
||||
"buidlerevm": {
|
||||
"address": "0x8D0206fEBEB380486729b64bB4cfEDC5b354a6D6",
|
||||
"address": "0x3c5408De7435Dfa3eB2aF2Edf5E39385f68F69b2",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xc072D8A233C8C52239dcD6ab39954240a0699055",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x417fc1038b2AF553D65F4fF2839efE9f93Ec1eac",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockFlashLoanReceiver": {
|
||||
"buidlerevm": {
|
||||
"address": "0xfC88832bac6AbdF216BC5A67be68E9DE94aD5ba2"
|
||||
"address": "0x0459c841b02Aee8730730C737582c53B20a27288"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x0459c841b02Aee8730730C737582c53B20a27288"
|
||||
}
|
||||
},
|
||||
"WalletBalanceProvider": {
|
||||
"buidlerevm": {
|
||||
"address": "0x1256eBA4d0a7A38D10BaF4F61775ba491Ce7EE25",
|
||||
"address": "0x77B0b5636fEA30eA79BB65AeCCdb599997A849A8",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"kovan": {
|
||||
"address": "0xf896A27CDd4E3bC101aCEa86cc1cE6b7C91AEFA1",
|
||||
"deployer": "0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x2530ce07D254eA185E8e0bCC37a39e2FbA3bE548",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockAToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x77B0b5636fEA30eA79BB65AeCCdb599997A849A8",
|
||||
"address": "0x0EBCa695959e5f138Af772FAa44ce1A9C7aEd921",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockStableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x78Ee8Fb9fE5abD5e347Fc94c2fb85596d1f60e3c",
|
||||
"address": "0x417fc1038b2AF553D65F4fF2839efE9f93Ec1eac",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MockVariableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x8BFFF31B1757da579Bb5B118489568526F7fb6D4",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x2cBbbBE1B75Ad7848F0844215816F551f429c64f",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"WETHGateway": {
|
||||
"buidlerevm": {
|
||||
"address": "0x0Cf45557d25a4e4c0F1aC65EF6c48ae67c61a0E6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"WETHMocked": {
|
||||
"buidlerevm": {
|
||||
"address": "0xf784709d2317D872237C4bC22f867d1BAe2913AB",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x0Cf45557d25a4e4c0F1aC65EF6c48ae67c61a0E6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"MintableDelegationERC20": {
|
||||
"buidlerevm": {
|
||||
"address": "0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"AAVE": {
|
||||
"buidlerevm": {
|
||||
"address": "0x8858eeB3DfffA017D4BCE9801D340D36Cf895CCf",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x8858eeB3DfffA017D4BCE9801D340D36Cf895CCf",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"REN": {
|
||||
"buidlerevm": {
|
||||
"address": "0x2D8553F9ddA85A9B3259F6Bf26911364B85556F5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x2D8553F9ddA85A9B3259F6Bf26911364B85556F5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"YFI": {
|
||||
"buidlerevm": {
|
||||
"address": "0x5bcb88A0d20426e451332eE6C4324b0e663c50E0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x5bcb88A0d20426e451332eE6C4324b0e663c50E0",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"UNI": {
|
||||
"buidlerevm": {
|
||||
"address": "0x3521eF8AaB0323004A6dD8b03CE890F4Ea3A13f5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x3521eF8AaB0323004A6dD8b03CE890F4Ea3A13f5",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"AToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"SelfdestructTransferMock": {
|
||||
"buidlerevm": {
|
||||
"address": "0x920d847fE49E54C19047ba8bc236C45A8068Bca7",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
"ENJ": {
|
||||
"buidlerevm": {
|
||||
"address": "0x53369fd4680FfE3DfF39Fc6DDa9CfbfD43daeA2E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"hardhat": {
|
||||
"address": "0x53369fd4680FfE3DfF39Fc6DDa9CfbfD43daeA2E",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
115
hardhat.config.ts
Normal file
115
hardhat.config.ts
Normal file
|
@ -0,0 +1,115 @@
|
|||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import {HardhatUserConfig} from 'hardhat/config';
|
||||
// @ts-ignore
|
||||
import {accounts} from './test-wallets.js';
|
||||
import {eEthereumNetwork} from './helpers/types';
|
||||
import {BUIDLEREVM_CHAINID, COVERAGE_CHAINID} from './helpers/buidler-constants';
|
||||
|
||||
import '@nomiclabs/hardhat-ethers';
|
||||
import '@nomiclabs/hardhat-waffle';
|
||||
import '@nomiclabs/hardhat-etherscan';
|
||||
import 'hardhat-gas-reporter';
|
||||
import 'hardhat-typechain';
|
||||
|
||||
const SKIP_LOAD = process.env.SKIP_LOAD === 'true';
|
||||
const DEFAULT_BLOCK_GAS_LIMIT = 12450000;
|
||||
const DEFAULT_GAS_PRICE = 10;
|
||||
const HARDFORK = 'istanbul';
|
||||
const INFURA_KEY = process.env.INFURA_KEY || '';
|
||||
const ETHERSCAN_KEY = process.env.ETHERSCAN_KEY || '';
|
||||
const MNEMONIC_PATH = "m/44'/60'/0'/0";
|
||||
const MNEMONIC = process.env.MNEMONIC || '';
|
||||
|
||||
// Prevent to load scripts before compilation and typechain
|
||||
if (!SKIP_LOAD) {
|
||||
['misc', 'migrations', 'dev', 'full'].forEach((folder) => {
|
||||
const tasksPath = path.join(__dirname, 'tasks', folder);
|
||||
fs.readdirSync(tasksPath)
|
||||
.filter((pth) => pth.includes('.ts'))
|
||||
.forEach((task) => {
|
||||
require(`${tasksPath}/${task}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
require(`${path.join(__dirname, 'tasks/misc')}/set-bre.ts`);
|
||||
|
||||
const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number) => {
|
||||
return {
|
||||
url: `https://${networkName}.infura.io/v3/${INFURA_KEY}`,
|
||||
hardfork: HARDFORK,
|
||||
blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT,
|
||||
gasMultiplier: DEFAULT_GAS_PRICE,
|
||||
chainId: networkId,
|
||||
accounts: {
|
||||
mnemonic: MNEMONIC,
|
||||
path: MNEMONIC_PATH,
|
||||
initialIndex: 0,
|
||||
count: 20,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const buidlerConfig: HardhatUserConfig = {
|
||||
solidity: {
|
||||
version: '0.6.8',
|
||||
settings: {
|
||||
optimizer: {enabled: true, runs: 200},
|
||||
evmVersion: 'istanbul',
|
||||
},
|
||||
},
|
||||
typechain: {
|
||||
outDir: 'types',
|
||||
target: 'ethers-v5',
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: ETHERSCAN_KEY,
|
||||
},
|
||||
mocha: {
|
||||
timeout: 0,
|
||||
},
|
||||
networks: {
|
||||
coverage: {
|
||||
url: 'http://localhost:8555',
|
||||
chainId: COVERAGE_CHAINID,
|
||||
},
|
||||
kovan: getCommonNetworkConfig(eEthereumNetwork.kovan, 42),
|
||||
ropsten: getCommonNetworkConfig(eEthereumNetwork.ropsten, 3),
|
||||
main: getCommonNetworkConfig(eEthereumNetwork.main, 1),
|
||||
hardhat: {
|
||||
hardfork: 'istanbul',
|
||||
blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT,
|
||||
gas: DEFAULT_BLOCK_GAS_LIMIT,
|
||||
gasPrice: 8000000000,
|
||||
chainId: BUIDLEREVM_CHAINID,
|
||||
throwOnTransactionFailures: true,
|
||||
throwOnCallFailures: true,
|
||||
accounts: accounts.map(({secretKey, balance}: {secretKey: string; balance: string}) => ({
|
||||
privateKey: secretKey,
|
||||
balance,
|
||||
})),
|
||||
},
|
||||
buidlerevm_docker: {
|
||||
hardfork: 'istanbul',
|
||||
blockGasLimit: 9500000,
|
||||
gas: 9500000,
|
||||
gasPrice: 8000000000,
|
||||
chainId: BUIDLEREVM_CHAINID,
|
||||
throwOnTransactionFailures: true,
|
||||
throwOnCallFailures: true,
|
||||
url: 'http://localhost:8545',
|
||||
},
|
||||
ganache: {
|
||||
url: 'http://ganache:8545',
|
||||
accounts: {
|
||||
mnemonic: 'fox sight canyon orphan hotel grow hedgehog build bless august weather swarm',
|
||||
path: "m/44'/60'/0'/0",
|
||||
initialIndex: 0,
|
||||
count: 20,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default buidlerConfig;
|
|
@ -12,9 +12,10 @@ import {AaveConfig} from '../config/aave';
|
|||
import {UniswapConfig} from '../config/uniswap';
|
||||
import {CommonsConfig} from '../config/commons';
|
||||
import {ZERO_ADDRESS} from './constants';
|
||||
import {BRE} from './misc-utils';
|
||||
import {DRE} from './misc-utils';
|
||||
import {tEthereumAddress} from './types';
|
||||
import {getParamPerNetwork} from './contracts-helpers';
|
||||
import {deployWETHMocked} from './contracts-deployments';
|
||||
|
||||
export enum ConfigNames {
|
||||
Commons = 'Commons',
|
||||
|
@ -52,27 +53,29 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets<IRes
|
|||
pool
|
||||
);
|
||||
|
||||
export const getFeeDistributionParamsCommon = (
|
||||
receiver: tEthereumAddress
|
||||
): iBasicDistributionParams => {
|
||||
const receivers = [receiver, ZERO_ADDRESS];
|
||||
const percentages = ['2000', '8000'];
|
||||
return {
|
||||
receivers,
|
||||
percentages,
|
||||
};
|
||||
};
|
||||
|
||||
export const getGenesisAaveAdmin = async (config: ICommonConfiguration) => {
|
||||
const currentNetwork = BRE.network.name;
|
||||
const targetAddress = getParamPerNetwork(config.AaveAdmin, <eEthereumNetwork>currentNetwork);
|
||||
export const getGenesisPoolAdmin = async (config: ICommonConfiguration) => {
|
||||
const currentNetwork = DRE.network.name;
|
||||
const targetAddress = getParamPerNetwork(config.PoolAdmin, <eEthereumNetwork>currentNetwork);
|
||||
if (targetAddress) {
|
||||
return targetAddress;
|
||||
}
|
||||
const addressList = await Promise.all(
|
||||
(await BRE.ethers.getSigners()).map((signer) => signer.getAddress())
|
||||
(await DRE.ethers.getSigners()).map((signer) => signer.getAddress())
|
||||
);
|
||||
const addressIndex = config.AaveAdminIndex;
|
||||
const addressIndex = config.PoolAdminIndex;
|
||||
return addressList[addressIndex];
|
||||
};
|
||||
|
||||
export const getEmergencyAdmin = async (config: ICommonConfiguration) => {
|
||||
const currentNetwork = DRE.network.name;
|
||||
const targetAddress = getParamPerNetwork(config.EmergencyAdmin, <eEthereumNetwork>currentNetwork);
|
||||
if (targetAddress) {
|
||||
return targetAddress;
|
||||
}
|
||||
const addressList = await Promise.all(
|
||||
(await DRE.ethers.getSigners()).map((signer) => signer.getAddress())
|
||||
);
|
||||
const addressIndex = config.EmergencyAdminIndex;
|
||||
return addressList[addressIndex];
|
||||
};
|
||||
|
||||
|
@ -80,3 +83,16 @@ export const getATokenDomainSeparatorPerNetwork = (
|
|||
network: eEthereumNetwork,
|
||||
config: ICommonConfiguration
|
||||
): tEthereumAddress => getParamPerNetwork<tEthereumAddress>(config.ATokenDomainSeparator, network);
|
||||
|
||||
export const getWethAddress = async (config: ICommonConfiguration) => {
|
||||
const currentNetwork = DRE.network.name;
|
||||
const wethAddress = getParamPerNetwork(config.WETH, <eEthereumNetwork>currentNetwork);
|
||||
if (wethAddress) {
|
||||
return wethAddress;
|
||||
}
|
||||
if (currentNetwork.includes('main')) {
|
||||
throw new Error('WETH not set at mainnet configuration.');
|
||||
}
|
||||
const weth = await deployWETHMocked();
|
||||
return weth.address;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {Contract} from 'ethers';
|
||||
import {BRE} from './misc-utils';
|
||||
import {DRE} from './misc-utils';
|
||||
import {
|
||||
tEthereumAddress,
|
||||
eContractid,
|
||||
|
@ -9,10 +9,10 @@ import {
|
|||
iMultiPoolsAssets,
|
||||
IReserveParams,
|
||||
PoolConfiguration,
|
||||
eEthereumNetwork,
|
||||
} from './types';
|
||||
|
||||
import {MintableErc20 as MintableERC20} from '../types/MintableErc20';
|
||||
import {readArtifact} from '@nomiclabs/buidler/plugins';
|
||||
import {MockContract} from 'ethereum-waffle';
|
||||
import {getReservesConfigByPool} from './configuration';
|
||||
import {getFirstSigner} from './contracts-getters';
|
||||
|
@ -23,6 +23,7 @@ import {
|
|||
ATokensAndRatesHelperFactory,
|
||||
ChainlinkProxyPriceProviderFactory,
|
||||
DefaultReserveInterestRateStrategyFactory,
|
||||
DelegationAwareATokenFactory,
|
||||
InitializableAdminUpgradeabilityProxyFactory,
|
||||
LendingPoolAddressesProviderFactory,
|
||||
LendingPoolAddressesProviderRegistryFactory,
|
||||
|
@ -31,6 +32,7 @@ import {
|
|||
LendingPoolFactory,
|
||||
LendingPoolLibraryAddresses,
|
||||
LendingRateOracleFactory,
|
||||
MintableDelegationErc20Factory,
|
||||
MintableErc20Factory,
|
||||
MockAggregatorFactory,
|
||||
MockATokenFactory,
|
||||
|
@ -40,17 +42,27 @@ import {
|
|||
MockUniswapV2Router02Factory,
|
||||
PriceOracleFactory,
|
||||
ReserveLogicFactory,
|
||||
SelfdestructTransferFactory,
|
||||
StableDebtTokenFactory,
|
||||
UniswapLiquiditySwapAdapterFactory,
|
||||
UniswapRepayAdapterFactory,
|
||||
VariableDebtTokenFactory,
|
||||
WalletBalanceProviderFactory,
|
||||
Weth9MockedFactory,
|
||||
WethGatewayFactory,
|
||||
} from '../types';
|
||||
import {withSaveAndVerify, registerContractInJsonDb, linkBytecode} from './contracts-helpers';
|
||||
import {StableAndVariableTokensHelperFactory} from '../types/StableAndVariableTokensHelperFactory';
|
||||
import {MockStableDebtToken} from '../types/MockStableDebtToken';
|
||||
import {MockVariableDebtToken} from '../types/MockVariableDebtToken';
|
||||
import {MintableDelegationErc20} from '../types/MintableDelegationErc20';
|
||||
import {readArtifact as buidlerReadArtifact} from '@nomiclabs/buidler/plugins';
|
||||
import {HardhatRuntimeEnvironment} from 'hardhat/types';
|
||||
|
||||
const readArtifact = async (id: string) => {
|
||||
if (DRE.network.name === eEthereumNetwork.buidlerevm) {
|
||||
return buidlerReadArtifact(DRE.config.paths.artifacts, id);
|
||||
}
|
||||
return (DRE as HardhatRuntimeEnvironment).artifacts.readArtifact(id);
|
||||
};
|
||||
export const deployLendingPoolAddressesProvider = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new LendingPoolAddressesProviderFactory(await getFirstSigner()).deploy(),
|
||||
|
@ -84,16 +96,13 @@ export const deployReserveLogicLibrary = async (verify?: boolean) =>
|
|||
);
|
||||
|
||||
export const deployGenericLogic = async (reserveLogic: Contract, verify?: boolean) => {
|
||||
const genericLogicArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.GenericLogic
|
||||
);
|
||||
const genericLogicArtifact = await readArtifact(eContractid.GenericLogic);
|
||||
|
||||
const linkedGenericLogicByteCode = linkBytecode(genericLogicArtifact, {
|
||||
[eContractid.ReserveLogic]: reserveLogic.address,
|
||||
});
|
||||
|
||||
const genericLogicFactory = await BRE.ethers.getContractFactory(
|
||||
const genericLogicFactory = await DRE.ethers.getContractFactory(
|
||||
genericLogicArtifact.abi,
|
||||
linkedGenericLogicByteCode
|
||||
);
|
||||
|
@ -107,17 +116,14 @@ export const deployValidationLogic = async (
|
|||
genericLogic: Contract,
|
||||
verify?: boolean
|
||||
) => {
|
||||
const validationLogicArtifact = await readArtifact(
|
||||
BRE.config.paths.artifacts,
|
||||
eContractid.ValidationLogic
|
||||
);
|
||||
const validationLogicArtifact = await readArtifact(eContractid.ValidationLogic);
|
||||
|
||||
const linkedValidationLogicByteCode = linkBytecode(validationLogicArtifact, {
|
||||
[eContractid.ReserveLogic]: reserveLogic.address,
|
||||
[eContractid.GenericLogic]: genericLogic.address,
|
||||
});
|
||||
|
||||
const validationLogicFactory = await BRE.ethers.getContractFactory(
|
||||
const validationLogicFactory = await DRE.ethers.getContractFactory(
|
||||
validationLogicArtifact.abi,
|
||||
linkedValidationLogicByteCode
|
||||
);
|
||||
|
@ -186,7 +192,7 @@ export const deployMockAggregator = async (price: tStringTokenSmallUnits, verify
|
|||
);
|
||||
|
||||
export const deployChainlinkProxyPriceProvider = async (
|
||||
args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress],
|
||||
args: [tEthereumAddress[], tEthereumAddress[], tEthereumAddress, tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
|
@ -257,6 +263,16 @@ export const deployMintableERC20 = async (
|
|||
verify
|
||||
);
|
||||
|
||||
export const deployMintableDelegationERC20 = async (
|
||||
args: [string, string, string],
|
||||
verify?: boolean
|
||||
): Promise<MintableDelegationErc20> =>
|
||||
withSaveAndVerify(
|
||||
await new MintableDelegationErc20Factory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.MintableDelegationERC20,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
export const deployDefaultReserveInterestRateStrategy = async (
|
||||
args: [tEthereumAddress, string, string, string, string, string],
|
||||
verify: boolean
|
||||
|
@ -316,6 +332,32 @@ export const deployGenericAToken = async (
|
|||
);
|
||||
};
|
||||
|
||||
export const deployDelegationAwareAToken = async (
|
||||
[poolAddress, underlyingAssetAddress, name, symbol, incentivesController]: [
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
string,
|
||||
string,
|
||||
tEthereumAddress
|
||||
],
|
||||
verify: boolean
|
||||
) => {
|
||||
const args: [
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
tEthereumAddress,
|
||||
string,
|
||||
string,
|
||||
tEthereumAddress
|
||||
] = [poolAddress, underlyingAssetAddress, ZERO_ADDRESS, name, symbol, incentivesController];
|
||||
return withSaveAndVerify(
|
||||
await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.AToken,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
};
|
||||
|
||||
export const deployAllMockTokens = async (verify?: boolean) => {
|
||||
const tokens: {[symbol: string]: MockContract | MintableERC20} = {};
|
||||
|
||||
|
@ -345,7 +387,7 @@ export const deployMockTokens = async (config: PoolConfiguration, verify?: boole
|
|||
|
||||
const configData = config.ReservesConfig;
|
||||
|
||||
for (const tokenSymbol of Object.keys(config.ReserveSymbols)) {
|
||||
for (const tokenSymbol of Object.keys(configData)) {
|
||||
tokens[tokenSymbol] = await deployMintableERC20(
|
||||
[
|
||||
tokenSymbol,
|
||||
|
@ -382,24 +424,43 @@ export const deployATokensAndRatesHelper = async (
|
|||
verify
|
||||
);
|
||||
|
||||
export const deployWETHGateway = async (
|
||||
args: [tEthereumAddress, tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new WethGatewayFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.WETHGateway,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployMockStableDebtToken = async (
|
||||
args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new MockStableDebtTokenFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.ATokensAndRatesHelper,
|
||||
eContractid.MockStableDebtToken,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployWETHMocked = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new Weth9MockedFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.WETHMocked,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployMockVariableDebtToken = async (
|
||||
args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
|
||||
verify?: boolean
|
||||
) =>
|
||||
withSaveAndVerify(
|
||||
await new MockVariableDebtTokenFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.ATokensAndRatesHelper,
|
||||
eContractid.MockVariableDebtToken,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
@ -410,11 +471,19 @@ export const deployMockAToken = async (
|
|||
) =>
|
||||
withSaveAndVerify(
|
||||
await new MockATokenFactory(await getFirstSigner()).deploy(...args),
|
||||
eContractid.ATokensAndRatesHelper,
|
||||
eContractid.MockAToken,
|
||||
args,
|
||||
verify
|
||||
);
|
||||
|
||||
export const deploySelfdestructTransferMock = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new SelfdestructTransferFactory(await getFirstSigner()).deploy(),
|
||||
eContractid.SelfdestructTransferMock,
|
||||
[],
|
||||
verify
|
||||
);
|
||||
|
||||
export const deployMockUniswapRouter = async (verify?: boolean) =>
|
||||
withSaveAndVerify(
|
||||
await new MockUniswapV2Router02Factory(await getFirstSigner()).deploy(),
|
||||
|
|
|
@ -17,23 +17,27 @@ import {
|
|||
MockUniswapV2Router02Factory,
|
||||
PriceOracleFactory,
|
||||
ReserveLogicFactory,
|
||||
SelfdestructTransferFactory,
|
||||
StableAndVariableTokensHelperFactory,
|
||||
StableDebtTokenFactory,
|
||||
UniswapLiquiditySwapAdapterFactory,
|
||||
UniswapRepayAdapterFactory,
|
||||
VariableDebtTokenFactory,
|
||||
Weth9Factory,
|
||||
Weth9MockedFactory,
|
||||
WethGatewayFactory,
|
||||
} from '../types';
|
||||
import {Ierc20DetailedFactory} from '../types/Ierc20DetailedFactory';
|
||||
import {MockTokenMap} from './contracts-helpers';
|
||||
import {BRE, getDb} from './misc-utils';
|
||||
import {DRE, getDb} from './misc-utils';
|
||||
import {eContractid, PoolConfiguration, tEthereumAddress, TokenContractId} from './types';
|
||||
|
||||
export const getFirstSigner = async () => (await BRE.ethers.getSigners())[0];
|
||||
export const getFirstSigner = async () => (await DRE.ethers.getSigners())[0];
|
||||
|
||||
export const getLendingPoolAddressesProvider = async (address?: tEthereumAddress) =>
|
||||
await LendingPoolAddressesProviderFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPoolAddressesProvider}.${BRE.network.name}`).value())
|
||||
(await getDb().get(`${eContractid.LendingPoolAddressesProvider}.${DRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
@ -41,7 +45,7 @@ export const getLendingPoolAddressesProvider = async (address?: tEthereumAddress
|
|||
export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress) => {
|
||||
return await LendingPoolConfiguratorFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPoolConfigurator}.${BRE.network.name}`).value())
|
||||
(await getDb().get(`${eContractid.LendingPoolConfigurator}.${DRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
@ -50,55 +54,55 @@ export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress
|
|||
export const getLendingPool = async (address?: tEthereumAddress) =>
|
||||
await LendingPoolFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingPool}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.LendingPool}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getPriceOracle = async (address?: tEthereumAddress) =>
|
||||
await PriceOracleFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.PriceOracle}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.PriceOracle}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getAToken = async (address?: tEthereumAddress) =>
|
||||
await ATokenFactory.connect(
|
||||
address || (await getDb().get(`${eContractid.AToken}.${BRE.network.name}`).value()).address,
|
||||
address || (await getDb().get(`${eContractid.AToken}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getStableDebtToken = async (address?: tEthereumAddress) =>
|
||||
await StableDebtTokenFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.StableDebtToken}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.StableDebtToken}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getVariableDebtToken = async (address?: tEthereumAddress) =>
|
||||
await VariableDebtTokenFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.VariableDebtToken}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.VariableDebtToken}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMintableErc20 = async (address: tEthereumAddress) =>
|
||||
await MintableErc20Factory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MintableERC20}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.MintableERC20}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getIErc20Detailed = async (address: tEthereumAddress) =>
|
||||
await Ierc20DetailedFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.IERC20Detailed}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.IERC20Detailed}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getAaveProtocolTestHelpers = async (address?: tEthereumAddress) =>
|
||||
await AaveProtocolTestHelpersFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.AaveProtocolTestHelpers}.${BRE.network.name}`).value())
|
||||
(await getDb().get(`${eContractid.AaveProtocolTestHelpers}.${DRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
@ -108,7 +112,7 @@ export const getInterestRateStrategy = async (address?: tEthereumAddress) =>
|
|||
address ||
|
||||
(
|
||||
await getDb()
|
||||
.get(`${eContractid.DefaultReserveInterestRateStrategy}.${BRE.network.name}`)
|
||||
.get(`${eContractid.DefaultReserveInterestRateStrategy}.${DRE.network.name}`)
|
||||
.value()
|
||||
).address,
|
||||
await getFirstSigner()
|
||||
|
@ -117,7 +121,7 @@ export const getInterestRateStrategy = async (address?: tEthereumAddress) =>
|
|||
export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) =>
|
||||
await MockFlashLoanReceiverFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MockFlashLoanReceiver}.${BRE.network.name}`).value())
|
||||
(await getDb().get(`${eContractid.MockFlashLoanReceiver}.${DRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
@ -125,17 +129,17 @@ export const getMockFlashLoanReceiver = async (address?: tEthereumAddress) =>
|
|||
export const getLendingRateOracle = async (address?: tEthereumAddress) =>
|
||||
await LendingRateOracleFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.LendingRateOracle}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.LendingRateOracle}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMockedTokens = async (config: PoolConfiguration) => {
|
||||
const tokenSymbols = config.ReserveSymbols;
|
||||
const tokenSymbols = Object.keys(config.ReservesConfig);
|
||||
const db = getDb();
|
||||
const tokens: MockTokenMap = await tokenSymbols.reduce<Promise<MockTokenMap>>(
|
||||
async (acc, tokenSymbol) => {
|
||||
const accumulator = await acc;
|
||||
const address = db.get(`${tokenSymbol.toUpperCase()}.${BRE.network.name}`).value().address;
|
||||
const address = db.get(`${tokenSymbol.toUpperCase()}.${DRE.network.name}`).value().address;
|
||||
accumulator[tokenSymbol] = await getMintableErc20(address);
|
||||
return Promise.resolve(acc);
|
||||
},
|
||||
|
@ -149,7 +153,7 @@ export const getAllMockedTokens = async () => {
|
|||
const tokens: MockTokenMap = await Object.keys(TokenContractId).reduce<Promise<MockTokenMap>>(
|
||||
async (acc, tokenSymbol) => {
|
||||
const accumulator = await acc;
|
||||
const address = db.get(`${tokenSymbol.toUpperCase()}.${BRE.network.name}`).value().address;
|
||||
const address = db.get(`${tokenSymbol.toUpperCase()}.${DRE.network.name}`).value().address;
|
||||
accumulator[tokenSymbol] = await getMintableErc20(address);
|
||||
return Promise.resolve(acc);
|
||||
},
|
||||
|
@ -190,7 +194,7 @@ export const getLendingPoolAddressesProviderRegistry = async (address?: tEthereu
|
|||
address ||
|
||||
(
|
||||
await getDb()
|
||||
.get(`${eContractid.LendingPoolAddressesProviderRegistry}.${BRE.network.name}`)
|
||||
.get(`${eContractid.LendingPoolAddressesProviderRegistry}.${DRE.network.name}`)
|
||||
.value()
|
||||
).address,
|
||||
await getFirstSigner()
|
||||
|
@ -199,14 +203,14 @@ export const getLendingPoolAddressesProviderRegistry = async (address?: tEthereu
|
|||
export const getReserveLogic = async (address?: tEthereumAddress) =>
|
||||
await ReserveLogicFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.ReserveLogic}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.ReserveLogic}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getGenericLogic = async (address?: tEthereumAddress) =>
|
||||
await GenericLogicFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.GenericLogic}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.GenericLogic}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
|
@ -215,7 +219,7 @@ export const getStableAndVariableTokensHelper = async (address?: tEthereumAddres
|
|||
address ||
|
||||
(
|
||||
await getDb()
|
||||
.get(`${eContractid.StableAndVariableTokensHelper}.${BRE.network.name}`)
|
||||
.get(`${eContractid.StableAndVariableTokensHelper}.${DRE.network.name}`)
|
||||
.value()
|
||||
).address,
|
||||
await getFirstSigner()
|
||||
|
@ -224,28 +228,50 @@ export const getStableAndVariableTokensHelper = async (address?: tEthereumAddres
|
|||
export const getATokensAndRatesHelper = async (address?: tEthereumAddress) =>
|
||||
await ATokensAndRatesHelperFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.ATokensAndRatesHelper}.${BRE.network.name}`).value())
|
||||
(await getDb().get(`${eContractid.ATokensAndRatesHelper}.${DRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getWETHGateway = async (address?: tEthereumAddress) =>
|
||||
await WethGatewayFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.WETHGateway}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getWETHMocked = async (address?: tEthereumAddress) =>
|
||||
await Weth9MockedFactory.connect(
|
||||
address || (await getDb().get(`${eContractid.WETHMocked}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMockAToken = async (address?: tEthereumAddress) =>
|
||||
await MockATokenFactory.connect(
|
||||
address || (await getDb().get(`${eContractid.MockAToken}.${BRE.network.name}`).value()).address,
|
||||
address || (await getDb().get(`${eContractid.MockAToken}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMockVariableDebtToken = async (address?: tEthereumAddress) =>
|
||||
await MockVariableDebtTokenFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MockVariableDebtToken}.${BRE.network.name}`).value())
|
||||
(await getDb().get(`${eContractid.MockVariableDebtToken}.${DRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getMockStableDebtToken = async (address?: tEthereumAddress) =>
|
||||
await MockStableDebtTokenFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.MockStableDebtToken}.${BRE.network.name}`).value()).address,
|
||||
(await getDb().get(`${eContractid.MockStableDebtToken}.${DRE.network.name}`).value()).address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
export const getSelfdestructTransferMock = async (address?: tEthereumAddress) =>
|
||||
await SelfdestructTransferFactory.connect(
|
||||
address ||
|
||||
(await getDb().get(`${eContractid.SelfdestructTransferMock}.${DRE.network.name}`).value())
|
||||
.address,
|
||||
await getFirstSigner()
|
||||
);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import {Contract, Signer, utils, ethers, BigNumberish} from 'ethers';
|
|||
import {signTypedData_v4} from 'eth-sig-util';
|
||||
import {fromRpcSig, ECDSASignature} from 'ethereumjs-util';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {getDb, BRE, waitForTx} from './misc-utils';
|
||||
import {getDb, DRE, waitForTx} from './misc-utils';
|
||||
import {
|
||||
tEthereumAddress,
|
||||
eContractid,
|
||||
|
@ -13,15 +13,16 @@ import {
|
|||
iParamsPerPool,
|
||||
} from './types';
|
||||
import {MintableErc20 as MintableERC20} from '../types/MintableErc20';
|
||||
import {Artifact} from '@nomiclabs/buidler/types';
|
||||
import {Artifact} from 'hardhat/types';
|
||||
import {Artifact as BuidlerArtifact} from '@nomiclabs/buidler/types';
|
||||
import {verifyContract} from './etherscan-verification';
|
||||
import {getIErc20Detailed} from './contracts-getters';
|
||||
|
||||
export type MockTokenMap = {[symbol: string]: MintableERC20};
|
||||
|
||||
export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => {
|
||||
const currentNetwork = BRE.network.name;
|
||||
if (currentNetwork !== 'buidlerevm' && !currentNetwork.includes('coverage')) {
|
||||
const currentNetwork = DRE.network.name;
|
||||
if (currentNetwork !== 'hardhat' && !currentNetwork.includes('coverage')) {
|
||||
console.log(`*** ${contractId} ***\n`);
|
||||
console.log(`Network: ${currentNetwork}`);
|
||||
console.log(`tx: ${contractInstance.deployTransaction.hash}`);
|
||||
|
@ -43,19 +44,19 @@ export const registerContractInJsonDb = async (contractId: string, contractInsta
|
|||
|
||||
export const insertContractAddressInDb = async (id: eContractid, address: tEthereumAddress) =>
|
||||
await getDb()
|
||||
.set(`${id}.${BRE.network.name}`, {
|
||||
.set(`${id}.${DRE.network.name}`, {
|
||||
address,
|
||||
})
|
||||
.write();
|
||||
|
||||
export const getEthersSigners = async (): Promise<Signer[]> =>
|
||||
await Promise.all(await BRE.ethers.getSigners());
|
||||
await Promise.all(await DRE.ethers.getSigners());
|
||||
|
||||
export const getEthersSignersAddresses = async (): Promise<tEthereumAddress[]> =>
|
||||
await Promise.all((await BRE.ethers.getSigners()).map((signer) => signer.getAddress()));
|
||||
await Promise.all((await DRE.ethers.getSigners()).map((signer) => signer.getAddress()));
|
||||
|
||||
export const getCurrentBlock = async () => {
|
||||
return BRE.ethers.provider.getBlockNumber();
|
||||
return DRE.ethers.provider.getBlockNumber();
|
||||
};
|
||||
|
||||
export const decodeAbiNumber = (data: string): number =>
|
||||
|
@ -65,7 +66,7 @@ export const deployContract = async <ContractType extends Contract>(
|
|||
contractName: string,
|
||||
args: any[]
|
||||
): Promise<ContractType> => {
|
||||
const contract = (await (await BRE.ethers.getContractFactory(contractName)).deploy(
|
||||
const contract = (await (await DRE.ethers.getContractFactory(contractName)).deploy(
|
||||
...args
|
||||
)) as ContractType;
|
||||
await waitForTx(contract.deployTransaction);
|
||||
|
@ -90,9 +91,9 @@ export const withSaveAndVerify = async <ContractType extends Contract>(
|
|||
export const getContract = async <ContractType extends Contract>(
|
||||
contractName: string,
|
||||
address: string
|
||||
): Promise<ContractType> => (await BRE.ethers.getContractAt(contractName, address)) as ContractType;
|
||||
): Promise<ContractType> => (await DRE.ethers.getContractAt(contractName, address)) as ContractType;
|
||||
|
||||
export const linkBytecode = (artifact: Artifact, libraries: any) => {
|
||||
export const linkBytecode = (artifact: BuidlerArtifact | Artifact, libraries: any) => {
|
||||
let bytecode = artifact.bytecode;
|
||||
|
||||
for (const [fileName, fileReferences] of Object.entries(artifact.linkReferences)) {
|
||||
|
@ -124,14 +125,14 @@ export const getParamPerNetwork = <T>(
|
|||
return coverage;
|
||||
case eEthereumNetwork.buidlerevm:
|
||||
return buidlerevm;
|
||||
case eEthereumNetwork.hardhat:
|
||||
return buidlerevm;
|
||||
case eEthereumNetwork.kovan:
|
||||
return kovan;
|
||||
case eEthereumNetwork.ropsten:
|
||||
return ropsten;
|
||||
case eEthereumNetwork.main:
|
||||
return main;
|
||||
default:
|
||||
return main;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import {exit} from 'process';
|
|||
import fs from 'fs';
|
||||
import globby from 'globby';
|
||||
import {file} from 'tmp-promise';
|
||||
import {BRE} from './misc-utils';
|
||||
import {DRE} from './misc-utils';
|
||||
|
||||
const listSolidityFiles = (dir: string) => globby(`${dir}/**/*.sol`);
|
||||
|
||||
|
@ -14,7 +14,7 @@ const fatalErrors = [
|
|||
export const SUPPORTED_ETHERSCAN_NETWORKS = ['main', 'ropsten', 'kovan'];
|
||||
|
||||
export const getEtherscanPath = async (contractName: string) => {
|
||||
const paths = await listSolidityFiles(BRE.config.paths.sources);
|
||||
const paths = await listSolidityFiles(DRE.config.paths.sources);
|
||||
const path = paths.find((p) => p.includes(contractName));
|
||||
if (!path) {
|
||||
throw new Error(
|
||||
|
@ -35,7 +35,7 @@ export const verifyContract = async (
|
|||
constructorArguments: (string | string[])[],
|
||||
libraries?: string
|
||||
) => {
|
||||
const currentNetwork = BRE.network.name;
|
||||
const currentNetwork = DRE.network.name;
|
||||
|
||||
if (!process.env.ETHERSCAN_KEY) {
|
||||
throw Error('Missing process.env.ETHERSCAN_KEY.');
|
||||
|
@ -52,7 +52,7 @@ export const verifyContract = async (
|
|||
'[ETHERSCAN][WARNING] Delaying Etherscan verification due their API can not find newly deployed contracts'
|
||||
);
|
||||
const msDelay = 3000;
|
||||
const times = 60;
|
||||
const times = 15;
|
||||
// Write a temporal file to host complex parameters for buidler-etherscan https://github.com/nomiclabs/buidler/tree/development/packages/buidler-etherscan#complex-arguments
|
||||
const {fd, path, cleanup} = await file({
|
||||
prefix: 'verify-params-',
|
||||
|
@ -82,7 +82,7 @@ export const runTaskWithRetry = async (
|
|||
|
||||
try {
|
||||
if (times) {
|
||||
await BRE.run(task, params);
|
||||
await DRE.run(task, params);
|
||||
cleanup();
|
||||
} else {
|
||||
cleanup();
|
||||
|
@ -107,7 +107,7 @@ export const runTaskWithRetry = async (
|
|||
};
|
||||
|
||||
export const checkVerification = () => {
|
||||
const currentNetwork = BRE.network.name;
|
||||
const currentNetwork = DRE.network.name;
|
||||
if (!process.env.ETHERSCAN_KEY) {
|
||||
console.error('Missing process.env.ETHERSCAN_KEY.');
|
||||
exit(3);
|
||||
|
|
|
@ -24,7 +24,7 @@ export const initReservesByHelper = async (
|
|||
const addressProvider = await getLendingPoolAddressesProvider();
|
||||
|
||||
// Set aTokenAndRatesDeployer as temporal admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(atokenAndRatesDeployer.address));
|
||||
await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address));
|
||||
|
||||
// CHUNK CONFIGURATION
|
||||
const tokensChunks = 4;
|
||||
|
@ -140,7 +140,7 @@ export const initReservesByHelper = async (
|
|||
}
|
||||
|
||||
// Set deployer back as admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(admin));
|
||||
await waitForTx(await addressProvider.setPoolAdmin(admin));
|
||||
};
|
||||
|
||||
export const getPairsTokenAggregator = (
|
||||
|
@ -207,7 +207,7 @@ export const enableReservesToBorrowByHelper = async (
|
|||
}
|
||||
if (tokens.length) {
|
||||
// Set aTokenAndRatesDeployer as temporal admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(atokenAndRatesDeployer.address));
|
||||
await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address));
|
||||
|
||||
// Deploy init per chunks
|
||||
const stableChunks = 20;
|
||||
|
@ -233,7 +233,7 @@ export const enableReservesToBorrowByHelper = async (
|
|||
console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`);
|
||||
}
|
||||
// Set deployer back as admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(admin));
|
||||
await waitForTx(await addressProvider.setPoolAdmin(admin));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -280,7 +280,7 @@ export const enableReservesAsCollateralByHelper = async (
|
|||
}
|
||||
if (tokens.length) {
|
||||
// Set aTokenAndRatesDeployer as temporal admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(atokenAndRatesDeployer.address));
|
||||
await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address));
|
||||
|
||||
// Deploy init per chunks
|
||||
const enableChunks = 20;
|
||||
|
@ -304,6 +304,6 @@ export const enableReservesAsCollateralByHelper = async (
|
|||
console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`);
|
||||
}
|
||||
// Set deployer back as admin
|
||||
await waitForTx(await addressProvider.setAaveAdmin(admin));
|
||||
await waitForTx(await addressProvider.setPoolAdmin(admin));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -4,9 +4,8 @@ import low from 'lowdb';
|
|||
import FileSync from 'lowdb/adapters/FileSync';
|
||||
import {WAD} from './constants';
|
||||
import {Wallet, ContractTransaction} from 'ethers';
|
||||
import {HardhatRuntimeEnvironment} from 'hardhat/types';
|
||||
import {BuidlerRuntimeEnvironment} from '@nomiclabs/buidler/types';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
|
||||
export const toWad = (value: string | number) => new BigNumber(value).times(WAD).toFixed();
|
||||
|
||||
|
@ -15,9 +14,11 @@ export const stringToBigNumber = (amount: string): BigNumber => new BigNumber(am
|
|||
|
||||
export const getDb = () => low(new FileSync('./deployed-contracts.json'));
|
||||
|
||||
export let BRE: BuidlerRuntimeEnvironment = {} as BuidlerRuntimeEnvironment;
|
||||
export const setBRE = (_BRE: BuidlerRuntimeEnvironment) => {
|
||||
BRE = _BRE;
|
||||
export let DRE:
|
||||
| HardhatRuntimeEnvironment
|
||||
| BuidlerRuntimeEnvironment = {} as HardhatRuntimeEnvironment;
|
||||
export const setDRE = (_DRE: HardhatRuntimeEnvironment | BuidlerRuntimeEnvironment) => {
|
||||
DRE = _DRE;
|
||||
};
|
||||
|
||||
export const sleep = (milliseconds: number) => {
|
||||
|
@ -26,21 +27,21 @@ export const sleep = (milliseconds: number) => {
|
|||
|
||||
export const createRandomAddress = () => Wallet.createRandom().address;
|
||||
|
||||
export const evmSnapshot = async () => await BRE.ethereum.send('evm_snapshot', []);
|
||||
export const evmSnapshot = async () => await DRE.ethers.provider.send('evm_snapshot', []);
|
||||
|
||||
export const evmRevert = async (id: string) => BRE.ethereum.send('evm_revert', [id]);
|
||||
export const evmRevert = async (id: string) => DRE.ethers.provider.send('evm_revert', [id]);
|
||||
|
||||
export const timeLatest = async () => {
|
||||
const block = await BRE.ethers.provider.getBlock('latest');
|
||||
const block = await DRE.ethers.provider.getBlock('latest');
|
||||
return new BigNumber(block.timestamp);
|
||||
};
|
||||
|
||||
export const advanceBlock = async (timestamp: number) =>
|
||||
await BRE.ethers.provider.send('evm_mine', [timestamp]);
|
||||
await DRE.ethers.provider.send('evm_mine', [timestamp]);
|
||||
|
||||
export const increaseTime = async (secondsToIncrease: number) => {
|
||||
await BRE.ethers.provider.send('evm_increaseTime', [secondsToIncrease]);
|
||||
await BRE.ethers.provider.send('evm_mine', []);
|
||||
await DRE.ethers.provider.send('evm_increaseTime', [secondsToIncrease]);
|
||||
await DRE.ethers.provider.send('evm_mine', []);
|
||||
};
|
||||
|
||||
export const waitForTx = async (tx: ContractTransaction) => await tx.wait(1);
|
||||
|
@ -62,3 +63,26 @@ export const chunk = <T>(arr: Array<T>, chunkSize: number): Array<Array<T>> => {
|
|||
[]
|
||||
);
|
||||
};
|
||||
|
||||
interface DbEntry {
|
||||
[network: string]: {
|
||||
deployer: string;
|
||||
address: string;
|
||||
};
|
||||
}
|
||||
|
||||
export const printContracts = () => {
|
||||
const network = DRE.network.name;
|
||||
const db = getDb();
|
||||
console.log('Contracts deployed at', network);
|
||||
console.log('---------------------------------');
|
||||
|
||||
const entries = Object.entries<DbEntry>(db.getState()).filter(([_k, value]) => !!value[network]);
|
||||
|
||||
const contractsPrint = entries.map(
|
||||
([key, value]: [string, DbEntry]) => `${key}: ${value[network].address}`
|
||||
);
|
||||
|
||||
console.log('N# Contracts:', entries.length);
|
||||
console.log(contractsPrint.join('\n'), '\n');
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import BigNumber from 'bignumber.js';
|
||||
import {MockTokenMap} from './contracts-helpers';
|
||||
|
||||
export interface SymbolMap<T> {
|
||||
[symbol: string]: T;
|
||||
|
@ -11,6 +10,7 @@ export enum eEthereumNetwork {
|
|||
ropsten = 'ropsten',
|
||||
main = 'main',
|
||||
coverage = 'coverage',
|
||||
hardhat = 'hardhat',
|
||||
}
|
||||
|
||||
export enum EthereumNetworkNames {
|
||||
|
@ -28,6 +28,7 @@ export enum eContractid {
|
|||
Example = 'Example',
|
||||
LendingPoolAddressesProvider = 'LendingPoolAddressesProvider',
|
||||
MintableERC20 = 'MintableERC20',
|
||||
MintableDelegationERC20 = 'MintableDelegationERC20',
|
||||
LendingPoolAddressesProviderRegistry = 'LendingPoolAddressesProviderRegistry',
|
||||
LendingPoolParametersProvider = 'LendingPoolParametersProvider',
|
||||
LendingPoolConfigurator = 'LendingPoolConfigurator',
|
||||
|
@ -47,6 +48,7 @@ export enum eContractid {
|
|||
WalletBalanceProvider = 'WalletBalanceProvider',
|
||||
AToken = 'AToken',
|
||||
MockAToken = 'MockAToken',
|
||||
DelegationAwareAToken = 'DelegationAwareAToken',
|
||||
MockStableDebtToken = 'MockStableDebtToken',
|
||||
MockVariableDebtToken = 'MockVariableDebtToken',
|
||||
AaveProtocolTestHelpers = 'AaveProtocolTestHelpers',
|
||||
|
@ -57,6 +59,11 @@ export enum eContractid {
|
|||
TokenDistributor = 'TokenDistributor',
|
||||
StableAndVariableTokensHelper = 'StableAndVariableTokensHelper',
|
||||
ATokensAndRatesHelper = 'ATokensAndRatesHelper',
|
||||
UiPoolDataProvider = 'UiPoolDataProvider',
|
||||
WETHGateway = 'WETHGateway',
|
||||
WETH = 'WETH',
|
||||
WETHMocked = 'WETHMocked',
|
||||
SelfdestructTransferMock = 'SelfdestructTransferMock',
|
||||
MockUniswapV2Router02 = 'MockUniswapV2Router02',
|
||||
UniswapLiquiditySwapAdapter = 'UniswapLiquiditySwapAdapter',
|
||||
UniswapRepayAdapter = 'UniswapRepayAdapter',
|
||||
|
@ -75,9 +82,13 @@ export enum eContractid {
|
|||
* - P = Pausable
|
||||
*/
|
||||
export enum ProtocolErrors {
|
||||
//common errors
|
||||
CALLER_NOT_POOL_ADMIN = '33', // 'The caller must be the pool admin'
|
||||
|
||||
//contract specific errors
|
||||
VL_AMOUNT_NOT_GREATER_THAN_0 = '1', // 'Amount must be greater than 0'
|
||||
VL_NO_ACTIVE_RESERVE = '2', // 'Action requires an active reserve'
|
||||
VL_NO_UNFREEZED_RESERVE = '3', // 'Action requires an unfreezed reserve'
|
||||
VL_RESERVE_FROZEN = '3', // 'Action requires an unfrozen reserve'
|
||||
VL_CURRENT_AVAILABLE_LIQUIDITY_NOT_ENOUGH = '4', // 'The current liquidity is not enough'
|
||||
VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE = '5', // 'User cannot withdraw more than the available balance'
|
||||
VL_TRANSFER_NOT_ALLOWED = '6', // 'Transfer cannot be allowed.'
|
||||
|
@ -87,7 +98,7 @@ export enum ProtocolErrors {
|
|||
VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD = '10', // 'Health factor is lesser than the liquidation threshold'
|
||||
VL_COLLATERAL_CANNOT_COVER_NEW_BORROW = '11', // 'There is not enough collateral to cover a new borrow'
|
||||
VL_STABLE_BORROWING_NOT_ENABLED = '12', // stable borrowing not enabled
|
||||
VL_CALLATERAL_SAME_AS_BORROWING_CURRENCY = '13', // collateral is (mostly) the same currency that is being borrowed
|
||||
VL_COLLATERAL_SAME_AS_BORROWING_CURRENCY = '13', // collateral is (mostly) the same currency that is being borrowed
|
||||
VL_AMOUNT_BIGGER_THAN_MAX_LOAN_SIZE_STABLE = '14', // 'The requested amount is greater than the max loan size in stable rate mode
|
||||
VL_NO_DEBT_OF_SELECTED_TYPE = '15', // 'for repayment of stable debt, the user needs to have stable debt, otherwise, he needs to have variable debt'
|
||||
VL_NO_EXPLICIT_AMOUNT_TO_REPAY_ON_BEHALF = '16', // 'To repay on behalf of an user an explicit amount to repay is needed'
|
||||
|
@ -101,13 +112,12 @@ export enum ProtocolErrors {
|
|||
LP_NOT_ENOUGH_LIQUIDITY_TO_BORROW = '24', // 'There is not enough liquidity available to borrow'
|
||||
LP_REQUESTED_AMOUNT_TOO_SMALL = '25', // 'The requested amount is too small for a FlashLoan.'
|
||||
LP_INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26', // 'The actual balance of the protocol is inconsistent'
|
||||
LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27', // 'The actual balance of the protocol is inconsistent'
|
||||
LP_CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27', // 'The caller is not the lending pool configurator'
|
||||
LP_INCONSISTENT_FLASHLOAN_PARAMS = '28',
|
||||
AT_CALLER_MUST_BE_LENDING_POOL = '29', // 'The caller of this function must be a lending pool'
|
||||
AT_CANNOT_GIVE_ALLVWANCE_TO_HIMSELF = '30', // 'User cannot give allowance to himself'
|
||||
AT_TRANSFER_AMOUNT_NOT_GT_0 = '31', // 'Transferred amount needs to be greater than zero'
|
||||
RL_RESERVE_ALREADY_INITIALIZED = '32', // 'Reserve has already been initialized'
|
||||
LPC_CALLER_NOT_AAVE_ADMIN = '33', // 'The caller must be the aave admin'
|
||||
LPC_RESERVE_LIQUIDITY_NOT_0 = '34', // 'The liquidity of the reserve needs to be 0'
|
||||
LPC_INVALID_ATOKEN_POOL_ADDRESS = '35', // 'The liquidity of the reserve needs to be 0'
|
||||
LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS = '36', // 'The liquidity of the reserve needs to be 0'
|
||||
|
@ -115,6 +125,7 @@ export enum ProtocolErrors {
|
|||
LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '38', // 'The liquidity of the reserve needs to be 0'
|
||||
LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS = '39', // 'The liquidity of the reserve needs to be 0'
|
||||
LPC_INVALID_ADDRESSES_PROVIDER_ID = '40', // 'The liquidity of the reserve needs to be 0'
|
||||
LPC_CALLER_NOT_EMERGENCY_ADMIN = '76', // 'The caller must be the emergencya admin'
|
||||
LPAPR_PROVIDER_NOT_REGISTERED = '41', // 'Provider is not registered'
|
||||
LPCM_HEALTH_FACTOR_NOT_BELOW_THRESHOLD = '42', // 'Health factor is not below the threshold'
|
||||
LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED = '43', // 'The collateral chosen cannot be liquidated'
|
||||
|
@ -133,12 +144,12 @@ export enum ProtocolErrors {
|
|||
AT_INVALID_MINT_AMOUNT = '56', //invalid amount to mint
|
||||
LP_FAILED_REPAY_WITH_COLLATERAL = '57',
|
||||
AT_INVALID_BURN_AMOUNT = '58', //invalid amount to burn
|
||||
LP_BORROW_ALLOWANCE_ARE_NOT_ENOUGH = '59', // User borrows on behalf, but allowance are too small
|
||||
LP_BORROW_ALLOWANCE_NOT_ENOUGH = '59', // User borrows on behalf, but allowance are too small
|
||||
LP_FAILED_COLLATERAL_SWAP = '60',
|
||||
LP_INVALID_EQUAL_ASSETS_TO_SWAP = '61',
|
||||
LP_REENTRANCY_NOT_ALLOWED = '62',
|
||||
LP_CALLER_MUST_BE_AN_ATOKEN = '63',
|
||||
P_IS_PAUSED = '64', // 'Pool is paused'
|
||||
LP_IS_PAUSED = '64', // 'Pool is paused'
|
||||
LP_NO_MORE_RESERVES_ALLOWED = '65',
|
||||
LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN = '66',
|
||||
RC_INVALID_LTV = '67',
|
||||
|
@ -174,7 +185,7 @@ export interface iAssetBase<T> {
|
|||
USDC: T;
|
||||
USDT: T;
|
||||
SUSD: T;
|
||||
LEND: T;
|
||||
AAVE: T;
|
||||
BAT: T;
|
||||
REP: T;
|
||||
MKR: T;
|
||||
|
@ -185,8 +196,11 @@ export interface iAssetBase<T> {
|
|||
ZRX: T;
|
||||
SNX: T;
|
||||
BUSD: T;
|
||||
|
||||
YFI: T;
|
||||
UNI: T;
|
||||
USD: T;
|
||||
REN: T;
|
||||
ENJ: T;
|
||||
|
||||
UNI_DAI_ETH: T;
|
||||
UNI_USDC_ETH: T;
|
||||
|
@ -207,7 +221,7 @@ export type iAavePoolAssets<T> = Pick<
|
|||
| 'USDC'
|
||||
| 'USDT'
|
||||
| 'SUSD'
|
||||
| 'LEND'
|
||||
| 'AAVE'
|
||||
| 'BAT'
|
||||
| 'REP'
|
||||
| 'MKR'
|
||||
|
@ -219,6 +233,10 @@ export type iAavePoolAssets<T> = Pick<
|
|||
| 'SNX'
|
||||
| 'BUSD'
|
||||
| 'WETH'
|
||||
| 'YFI'
|
||||
| 'UNI'
|
||||
| 'REN'
|
||||
| 'ENJ'
|
||||
>;
|
||||
|
||||
export type iUniAssets<T> = Pick<
|
||||
|
@ -248,7 +266,7 @@ export type iAssetAggregatorBase<T> = iAssetsWithoutETH<T>;
|
|||
|
||||
export enum TokenContractId {
|
||||
DAI = 'DAI',
|
||||
LEND = 'LEND',
|
||||
AAVE = 'AAVE',
|
||||
TUSD = 'TUSD',
|
||||
BAT = 'BAT',
|
||||
WETH = 'WETH',
|
||||
|
@ -262,9 +280,13 @@ export enum TokenContractId {
|
|||
KNC = 'KNC',
|
||||
MANA = 'MANA',
|
||||
REP = 'REP',
|
||||
REN = 'REN',
|
||||
SNX = 'SNX',
|
||||
BUSD = 'BUSD',
|
||||
USD = 'USD',
|
||||
YFI = 'YFI',
|
||||
UNI = 'UNI',
|
||||
ENJ = 'ENJ',
|
||||
UNI_DAI_ETH = 'UNI_DAI_ETH',
|
||||
UNI_USDC_ETH = 'UNI_USDC_ETH',
|
||||
UNI_SETH_ETH = 'UNI_SETH_ETH',
|
||||
|
@ -301,6 +323,7 @@ export interface iParamsPerNetwork<T> {
|
|||
[eEthereumNetwork.kovan]: T;
|
||||
[eEthereumNetwork.ropsten]: T;
|
||||
[eEthereumNetwork.main]: T;
|
||||
[eEthereumNetwork.hardhat]: T;
|
||||
}
|
||||
|
||||
export interface iParamsPerPool<T> {
|
||||
|
@ -360,7 +383,6 @@ export interface ILendingRate {
|
|||
export interface ICommonConfiguration {
|
||||
ConfigName: string;
|
||||
ProviderId: number;
|
||||
ReserveSymbols: string[];
|
||||
ProtocolGlobalParams: IProtocolGlobalConfig;
|
||||
Mocks: IMocksConfig;
|
||||
ProviderRegistry: iParamsPerNetwork<tEthereumAddress | undefined>;
|
||||
|
@ -370,12 +392,15 @@ export interface ICommonConfiguration {
|
|||
ChainlinkProxyPriceProvider: iParamsPerNetwork<tEthereumAddress>;
|
||||
FallbackOracle: iParamsPerNetwork<tEthereumAddress>;
|
||||
ChainlinkAggregator: iParamsPerNetwork<ITokenAddress>;
|
||||
AaveAdmin: iParamsPerNetwork<tEthereumAddress | undefined>;
|
||||
AaveAdminIndex: number;
|
||||
PoolAdmin: iParamsPerNetwork<tEthereumAddress | undefined>;
|
||||
PoolAdminIndex: number;
|
||||
EmergencyAdmin: iParamsPerNetwork<tEthereumAddress | undefined>;
|
||||
EmergencyAdminIndex: number;
|
||||
ReserveAssets: iParamsPerNetwork<SymbolMap<tEthereumAddress>>;
|
||||
ReservesConfig: iMultiPoolsAssets<IReserveParams>;
|
||||
ATokenDomainSeparator: iParamsPerNetwork<string>;
|
||||
ProxyPriceProvider: iParamsPerNetwork<tEthereumAddress>;
|
||||
WETH: iParamsPerNetwork<tEthereumAddress>;
|
||||
}
|
||||
|
||||
export interface IAaveConfiguration extends ICommonConfiguration {
|
||||
|
|
7920
package-lock.json
generated
7920
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
103
package.json
103
package.json
|
@ -4,56 +4,65 @@
|
|||
"description": "Aave Protocol V2 smart contracts",
|
||||
"scripts": {
|
||||
"run-env": "npm i && tail -f /dev/null",
|
||||
"buidler": "buidler",
|
||||
"buidler:kovan": "buidler --network kovan",
|
||||
"buidler:ropsten": "buidler--network ropsten",
|
||||
"buidler:main": "buidler --network main",
|
||||
"buidler:docker": "buidler --network buidlerevm_docker",
|
||||
"buidler help": "buidler help",
|
||||
"compile": "SKIP_LOAD=true buidler compile",
|
||||
"types-gen": "npm run compile -- --force && typechain --target ethers-v5 --outDir ./types './artifacts/*.json'",
|
||||
"test": "buidler test",
|
||||
"test-scenarios": "buidler test test/__setup.spec.ts test/scenario.spec.ts",
|
||||
"aave:evm:dev:migration": "buidler aave:dev",
|
||||
"aave:evm:full:migration": "buidler aave:full",
|
||||
"aave:docker:dev:migration": "npm run buidler:docker -- aave:dev",
|
||||
"aave:docker:full:migration": "npm run buidler:docker -- aave:full",
|
||||
"aave:kovan:dev:migration": "npm run buidler:kovan -- aave:dev --verify",
|
||||
"aave:kovan:full:migration": "npm run buidler:kovan -- aave:full --verify",
|
||||
"aave:ropsten:dev:migration": "npm run buidler:ropsten -- aave:dev --verify",
|
||||
"aave:ropsten:full:migration": "npm run buidler:ropsten -- aave:full --verify",
|
||||
"aave:main:dev:migration": "npm run buidler:main -- aave:dev --verify",
|
||||
"aave:main:full:migration": "npm run buidler:main -- aave:full --verify",
|
||||
"uniswap:evm:dev:migration": "buidler uniswap:dev",
|
||||
"uniswap:evm:full:migration": "buidler uniswap:full --verify",
|
||||
"uniswap:kovan:dev:migration": "npm run buidler:kovan -- uniswap:dev --verify",
|
||||
"uniswap:kovan:full:migration": "npm run buidler:kovan -- uniswap:full --verify",
|
||||
"uniswap:ropsten:dev:migration": "npm run buidler:ropsten -- uniswap:dev --verify",
|
||||
"uniswap:ropsten:full:migration": "npm run buidler:ropsten -- uniswap:full --verify",
|
||||
"uniswap:main:dev:migration": "npm run buidler:main -- uniswap:dev --verify",
|
||||
"uniswap:main:full:migration": "npm run buidler:main -- uniswap:full --verify",
|
||||
"test-repay-with-collateral": "buidler test test/__setup.spec.ts test/repay-with-collateral.spec.ts",
|
||||
"test-liquidate-with-collateral": "buidler test test/__setup.spec.ts test/flash-liquidation-with-collateral.spec.ts",
|
||||
"test-transfers": "buidler test test/__setup.spec.ts test/atoken-transfer.spec.ts",
|
||||
"test-flash": "buidler test test/__setup.spec.ts test/flashloan.spec.ts",
|
||||
"test-liquidate": "buidler test test/__setup.spec.ts test/liquidation-atoken.spec.ts",
|
||||
"test-deploy": "buidler test test/__setup.spec.ts test/test-init.spec.ts",
|
||||
"test-pausable": "buidler test test/__setup.spec.ts test/pausable-functions.spec.ts",
|
||||
"test-permit": "buidler test test/__setup.spec.ts test/atoken-permit.spec.ts",
|
||||
"test-stable-and-atokens": "buidler test test/__setup.spec.ts test/atoken-transfer.spec.ts test/stable-token.spec.ts",
|
||||
"test-subgraph:scenarios": "buidler --network buidlerevm_docker test test/__setup.spec.ts test/subgraph-scenarios.spec.ts",
|
||||
"dev:coverage": "buidler coverage --network coverage",
|
||||
"dev:deployment": "buidler dev-deployment",
|
||||
"dev:deployExample": "buidler deploy-Example",
|
||||
"hardhat": "hardhat",
|
||||
"hardhat:kovan": "hardhat --network kovan",
|
||||
"hardhat:ropsten": "hardhat--network ropsten",
|
||||
"hardhat:main": "hardhat --network main",
|
||||
"hardhat:docker": "hardhat --network hardhatevm_docker",
|
||||
"compile": "SKIP_LOAD=true hardhat compile",
|
||||
"test": "SKIP_LOAD=true TS_NODE_TRANSPILE_ONLY=1 hardhat test",
|
||||
"test-scenarios": "npm run test -- test/__setup.spec.ts test/scenario.spec.ts",
|
||||
"aave:evm:dev:migration": "hardhat aave:dev",
|
||||
"aave:evm:full:migration": "hardhat aave:full",
|
||||
"aave:docker:dev:migration": "npm run hardhat:docker -- aave:dev",
|
||||
"aave:docker:full:migration": "npm run hardhat:docker -- aave:full",
|
||||
"aave:kovan:dev:migration": "npm run hardhat:kovan -- aave:dev --verify",
|
||||
"aave:kovan:full:migration": "npm run hardhat:kovan -- aave:full --verify",
|
||||
"aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave",
|
||||
"aave:ropsten:dev:migration": "npm run hardhat:ropsten -- aave:dev --verify",
|
||||
"aave:ropsten:full:migration": "npm run hardhat:ropsten -- aave:full --verify",
|
||||
"aave:main:dev:migration": "npm run hardhat:main -- aave:dev --verify",
|
||||
"aave:main:full:migration": "npm run hardhat:main -- aave:full --verify",
|
||||
"uniswap:evm:dev:migration": "hardhat uniswap:dev",
|
||||
"uniswap:evm:full:migration": "hardhat uniswap:full --verify",
|
||||
"uniswap:kovan:dev:migration": "npm run hardhat:kovan -- uniswap:dev --verify",
|
||||
"uniswap:kovan:full:migration": "npm run hardhat:kovan -- uniswap:full --verify",
|
||||
"uniswap:ropsten:dev:migration": "npm run hardhat:ropsten -- uniswap:dev --verify",
|
||||
"uniswap:ropsten:full:migration": "npm run hardhat:ropsten -- uniswap:full --verify",
|
||||
"uniswap:main:dev:migration": "npm run hardhat:main -- uniswap:dev --verify",
|
||||
"uniswap:main:full:migration": "npm run hardhat:main -- uniswap:full --verify",
|
||||
"test-repay-with-collateral": "hardhat test test/__setup.spec.ts test/repay-with-collateral.spec.ts",
|
||||
"test-liquidate-with-collateral": "hardhat test test/__setup.spec.ts test/flash-liquidation-with-collateral.spec.ts",
|
||||
"test-liquidate-underlying": "hardhat test test/__setup.spec.ts test/liquidation-underlying.spec.ts",
|
||||
"test-configurator": "hardhat test test/__setup.spec.ts test/configurator.spec.ts",
|
||||
"test-transfers": "hardhat test test/__setup.spec.ts test/atoken-transfer.spec.ts",
|
||||
"test-flash": "hardhat test test/__setup.spec.ts test/flashloan.spec.ts",
|
||||
"test-liquidate": "hardhat test test/__setup.spec.ts test/liquidation-atoken.spec.ts",
|
||||
"test-deploy": "hardhat test test/__setup.spec.ts test/test-init.spec.ts",
|
||||
"test-pausable": "hardhat test test/__setup.spec.ts test/pausable-functions.spec.ts",
|
||||
"test-permit": "hardhat test test/__setup.spec.ts test/atoken-permit.spec.ts",
|
||||
"test-stable-and-atokens": "hardhat test test/__setup.spec.ts test/atoken-transfer.spec.ts test/stable-token.spec.ts",
|
||||
"test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test/__setup.spec.ts test/subgraph-scenarios.spec.ts",
|
||||
"test-weth": "hardhat test test/__setup.spec.ts test/weth-gateway.spec.ts",
|
||||
"dev:coverage": "buidler compile --force && buidler coverage --network coverage",
|
||||
"dev:deployment": "hardhat dev-deployment",
|
||||
"dev:deployExample": "hardhat deploy-Example",
|
||||
"dev:prettier": "prettier --write .",
|
||||
"ci:test": "npm run compile && npm run types-gen && npm run test",
|
||||
"ci:clean": "rm -rf ./artifacts ./cache ./types"
|
||||
"ci:test": "npm run compile && npm run test",
|
||||
"ci:clean": "rm -rf ./artifacts ./cache ./types",
|
||||
"print-contracts:kovan": "npm run hardhat:kovan -- print-contracts",
|
||||
"print-contracts:main": "npm run hardhat:main -- print-contracts",
|
||||
"print-contracts:ropsten": "npm run hardhat:main -- print-contracts",
|
||||
"dev:deployUIProvider": "npm run buidler:kovan deploy-UiPoolDataProvider"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nomiclabs/buidler": "^1.4.7",
|
||||
"@nomiclabs/buidler-ethers": "2.0.0",
|
||||
"@nomiclabs/buidler-etherscan": "^2.1.0",
|
||||
"@nomiclabs/buidler-waffle": "2.0.0",
|
||||
"@nomiclabs/hardhat-ethers": "^2.0.0",
|
||||
"@nomiclabs/hardhat-etherscan": "^2.0.0",
|
||||
"@nomiclabs/hardhat-waffle": "^2.0.0",
|
||||
"@openzeppelin/contracts": "3.1.0",
|
||||
"@typechain/ethers-v4": "1.0.0",
|
||||
"@typechain/ethers-v5": "^1.0.0",
|
||||
|
@ -70,11 +79,15 @@
|
|||
"chai": "4.2.0",
|
||||
"chai-bignumber": "3.0.0",
|
||||
"chai-bn": "^0.2.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"eth-sig-util": "2.5.3",
|
||||
"ethereum-waffle": "3.0.2",
|
||||
"ethereumjs-util": "7.0.2",
|
||||
"ethers": "5.0.8",
|
||||
"globby": "^11.0.1",
|
||||
"hardhat": "^2.0.2",
|
||||
"hardhat-gas-reporter": "^1.0.0",
|
||||
"hardhat-typechain": "^0.3.3",
|
||||
"husky": "^4.2.5",
|
||||
"lowdb": "1.0.0",
|
||||
"prettier": "^2.0.5",
|
||||
|
@ -82,12 +95,12 @@
|
|||
"pretty-quick": "^2.0.1",
|
||||
"solidity-coverage": "0.7.10",
|
||||
"ts-generator": "0.0.8",
|
||||
"ts-node": "8.10.2",
|
||||
"ts-node": "^8.10.2",
|
||||
"tslint": "^6.1.2",
|
||||
"tslint-config-prettier": "^1.18.0",
|
||||
"tslint-plugin-prettier": "^2.3.0",
|
||||
"typechain": "2.0.0",
|
||||
"typescript": "3.9.3"
|
||||
"typescript": "^3.9.3"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
|
|
@ -8,6 +8,9 @@ import {UserConfiguration} from '../../contracts/libraries/configuration/UserCon
|
|||
import {ReserveLogic} from '../../contracts/libraries/logic/ReserveLogic.sol';
|
||||
import {ILendingPool} from '../../contracts/interfaces/ILendingPool.sol';
|
||||
import {LendingPool} from '../../contracts/lendingpool/LendingPool.sol';
|
||||
import {
|
||||
ILendingPoolAddressesProvider
|
||||
} from '../../contracts/interfaces/ILendingPoolAddressesProvider.sol';
|
||||
|
||||
/*
|
||||
Certora: Harness that delegates calls to the original LendingPool.
|
||||
|
@ -25,26 +28,12 @@ contract LendingPoolHarnessForVariableDebtToken is ILendingPool {
|
|||
originalPool.deposit(asset, amount, onBehalfOf, referralCode);
|
||||
}
|
||||
|
||||
function withdraw(address asset, uint256 amount) external override {
|
||||
originalPool.withdraw(asset, amount);
|
||||
}
|
||||
|
||||
function getBorrowAllowance(
|
||||
address fromUser,
|
||||
address toUser,
|
||||
function withdraw(
|
||||
address asset,
|
||||
uint256 interestRateMode
|
||||
) external override view returns (uint256) {
|
||||
return originalPool.getBorrowAllowance(fromUser, toUser, asset, interestRateMode);
|
||||
}
|
||||
|
||||
function delegateBorrowAllowance(
|
||||
address asset,
|
||||
address user,
|
||||
uint256 interestRateMode,
|
||||
uint256 amount
|
||||
uint256 amount,
|
||||
address to
|
||||
) external override {
|
||||
originalPool.delegateBorrowAllowance(asset, user, interestRateMode, amount);
|
||||
originalPool.withdraw(asset, amount, to);
|
||||
}
|
||||
|
||||
function borrow(
|
||||
|
@ -193,12 +182,12 @@ contract LendingPoolHarnessForVariableDebtToken is ILendingPool {
|
|||
address receiver,
|
||||
address[] calldata assets,
|
||||
uint256[] calldata amounts,
|
||||
uint256 mode,
|
||||
uint256[] calldata modes,
|
||||
address onBehalfOf,
|
||||
bytes calldata params,
|
||||
uint16 referralCode
|
||||
) external override {
|
||||
originalPool.flashLoan(receiver, assets, amounts, mode, onBehalfOf, params, referralCode);
|
||||
originalPool.flashLoan(receiver, assets, amounts, modes, onBehalfOf, params, referralCode);
|
||||
}
|
||||
|
||||
function finalizeTransfer(
|
||||
|
@ -211,4 +200,8 @@ contract LendingPoolHarnessForVariableDebtToken is ILendingPool {
|
|||
) external override {
|
||||
originalPool.finalizeTransfer(asset, from, to, amount, balanceFromAfter, balanceToBefore);
|
||||
}
|
||||
|
||||
function getAddressesProvider() external override view returns (ILendingPoolAddressesProvider) {
|
||||
return originalPool.getAddressesProvider();
|
||||
}
|
||||
}
|
||||
|
|
27
tasks/deployments/deploy-UiPoolDataProvider.ts
Normal file
27
tasks/deployments/deploy-UiPoolDataProvider.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
|
||||
import {UiPoolDataProviderFactory} from '../../types';
|
||||
import {verifyContract} from '../../helpers/etherscan-verification';
|
||||
import {eContractid} from '../../helpers/types';
|
||||
|
||||
task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider contract`)
|
||||
.addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
|
||||
if (!localBRE.network.config.chainId) {
|
||||
throw new Error('INVALID_CHAIN_ID');
|
||||
}
|
||||
|
||||
console.log(`\n- UiPoolDataProvider deployment`);
|
||||
|
||||
console.log(`\tDeploying UiPoolDataProvider implementation ...`);
|
||||
const uiPoolDataProvider = await new UiPoolDataProviderFactory(
|
||||
await localBRE.ethers.provider.getSigner()
|
||||
).deploy();
|
||||
await uiPoolDataProvider.deployTransaction.wait();
|
||||
console.log('uiPoolDataProvider.address', uiPoolDataProvider.address);
|
||||
await verifyContract(eContractid.UiPoolDataProvider, uiPoolDataProvider.address, []);
|
||||
|
||||
console.log(`\tFinished UiPoolDataProvider proxy and implementation deployment`);
|
||||
});
|
|
@ -1,8 +1,9 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {deployAllMockTokens} from '../../helpers/contracts-deployments';
|
||||
|
||||
task('dev:deploy-mock-tokens', 'Deploy mock tokens for dev enviroment')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
await deployAllMockTokens(verify);
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {
|
||||
deployLendingPoolAddressesProvider,
|
||||
deployLendingPoolAddressesProviderRegistry,
|
||||
|
@ -9,14 +9,14 @@ task(
|
|||
'dev:deploy-address-provider',
|
||||
'Deploy address provider, registry and fee provider for dev enviroment'
|
||||
)
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
const admin = await (await localBRE.ethers.getSigners())[0].getAddress();
|
||||
|
||||
const addressesProvider = await deployLendingPoolAddressesProvider(verify);
|
||||
await waitForTx(await addressesProvider.setAaveAdmin(admin));
|
||||
await waitForTx(await addressesProvider.setPoolAdmin(admin));
|
||||
|
||||
const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry(verify);
|
||||
await waitForTx(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {
|
||||
deployATokensAndRatesHelper,
|
||||
deployLendingPool,
|
||||
|
@ -15,9 +15,9 @@ import {
|
|||
import {insertContractAddressInDb} from '../../helpers/contracts-helpers';
|
||||
|
||||
task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {
|
||||
deployPriceOracle,
|
||||
deployChainlinkProxyPriceProvider,
|
||||
|
@ -13,7 +13,7 @@ import {
|
|||
import {ICommonConfiguration, iAssetBase, TokenContractId} from '../../helpers/types';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {getAllAggregatorsAddresses, getAllTokenAddresses} from '../../helpers/mock-helpers';
|
||||
import {ConfigNames, loadPoolConfig} from '../../helpers/configuration';
|
||||
import {ConfigNames, loadPoolConfig, getWethAddress} from '../../helpers/configuration';
|
||||
import {
|
||||
getAllMockedTokens,
|
||||
getLendingPoolAddressesProvider,
|
||||
|
@ -21,10 +21,10 @@ import {
|
|||
} from '../../helpers/contracts-getters';
|
||||
|
||||
task('dev:deploy-oracles', 'Deploy oracles for dev enviroment')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
|
||||
.setAction(async ({verify, pool}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
const poolConfig = loadPoolConfig(pool);
|
||||
const {
|
||||
Mocks: {ChainlinkAggregatorPrices, AllAssetsInitialPrices},
|
||||
|
@ -42,7 +42,7 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment')
|
|||
return prev;
|
||||
}, defaultTokenList);
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
const admin = await addressesProvider.getAaveAdmin();
|
||||
const admin = await addressesProvider.getPoolAdmin();
|
||||
|
||||
const fallbackOracle = await deployPriceOracle(verify);
|
||||
await waitForTx(await fallbackOracle.setEthUsdPrice(MockUsdPriceInWei));
|
||||
|
@ -58,7 +58,10 @@ task('dev:deploy-oracles', 'Deploy oracles for dev enviroment')
|
|||
allAggregatorsAddresses
|
||||
);
|
||||
|
||||
await deployChainlinkProxyPriceProvider([tokens, aggregators, fallbackOracle.address], verify);
|
||||
await deployChainlinkProxyPriceProvider(
|
||||
[tokens, aggregators, fallbackOracle.address, await getWethAddress(poolConfig)],
|
||||
verify
|
||||
);
|
||||
await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address));
|
||||
|
||||
const lendingRateOracle = await deployLendingRateOracle(verify);
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {
|
||||
deployLendingPoolCollateralManager,
|
||||
deployMockFlashLoanReceiver,
|
||||
deployWalletBalancerProvider,
|
||||
deployAaveProtocolTestHelpers,
|
||||
deployWETHGateway,
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {getReservesConfigByPool} from '../../helpers/configuration';
|
||||
import {
|
||||
ConfigNames,
|
||||
getReservesConfigByPool,
|
||||
getWethAddress,
|
||||
loadPoolConfig,
|
||||
} from '../../helpers/configuration';
|
||||
|
||||
import {tEthereumAddress, AavePools, eContractid} from '../../helpers/types';
|
||||
import {waitForTx, filterMapBy} from '../../helpers/misc-utils';
|
||||
|
@ -16,35 +22,30 @@ import {
|
|||
} from '../../helpers/init-helpers';
|
||||
import {getAllTokenAddresses} from '../../helpers/mock-helpers';
|
||||
import {ZERO_ADDRESS} from '../../helpers/constants';
|
||||
import {
|
||||
getAllMockedTokens,
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
getLendingPoolAddressesProvider,
|
||||
} from '../../helpers/contracts-getters';
|
||||
import {getAllMockedTokens, getLendingPoolAddressesProvider} from '../../helpers/contracts-getters';
|
||||
import {insertContractAddressInDb} from '../../helpers/contracts-helpers';
|
||||
|
||||
task('dev:initialize-lending-pool', 'Initialize lending pool configuration.')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
|
||||
.setAction(async ({verify, pool}, localBRE) => {
|
||||
await localBRE.run('set-DRE');
|
||||
const poolConfig = loadPoolConfig(pool);
|
||||
|
||||
const mockTokens = await getAllMockedTokens();
|
||||
const lendingPoolProxy = await getLendingPool();
|
||||
const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy();
|
||||
const allTokenAddresses = getAllTokenAddresses(mockTokens);
|
||||
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
|
||||
const protoPoolReservesAddresses = <{[symbol: string]: tEthereumAddress}>(
|
||||
filterMapBy(allTokenAddresses, (key: string) => !key.includes('UNI'))
|
||||
filterMapBy(allTokenAddresses, (key: string) => !key.includes('UNI_'))
|
||||
);
|
||||
|
||||
const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address, verify);
|
||||
|
||||
const reservesParams = getReservesConfigByPool(AavePools.proto);
|
||||
|
||||
const admin = await addressesProvider.getAaveAdmin();
|
||||
const admin = await addressesProvider.getPoolAdmin();
|
||||
|
||||
await initReservesByHelper(reservesParams, protoPoolReservesAddresses, admin, ZERO_ADDRESS);
|
||||
await enableReservesToBorrowByHelper(
|
||||
|
@ -77,4 +78,8 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.')
|
|||
await deployWalletBalancerProvider(addressesProvider.address, verify);
|
||||
|
||||
await insertContractAddressInDb(eContractid.AaveProtocolTestHelpers, testHelpers.address);
|
||||
|
||||
const lendingPoolAddress = await addressesProvider.getLendingPool();
|
||||
const wethAddress = await getWethAddress(poolConfig);
|
||||
await deployWETHGateway([wethAddress, lendingPoolAddress]);
|
||||
});
|
||||
|
|
13
tasks/dev/6_wallet_balance_provider.ts
Normal file
13
tasks/dev/6_wallet_balance_provider.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import {task} from 'hardhat/config';
|
||||
import {deployWalletBalancerProvider} from '../../helpers/contracts-deployments';
|
||||
|
||||
import {getLendingPoolAddressesProvider} from '../../helpers/contracts-getters';
|
||||
|
||||
task('dev:wallet-balance-provider', 'Initialize lending pool configuration.')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
await deployWalletBalancerProvider(addressesProvider.address, verify);
|
||||
});
|
|
@ -1,11 +1,16 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {getParamPerNetwork} from '../../helpers/contracts-helpers';
|
||||
import {
|
||||
deployLendingPoolAddressesProvider,
|
||||
deployLendingPoolAddressesProviderRegistry,
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {ConfigNames, loadPoolConfig, getGenesisAaveAdmin} from '../../helpers/configuration';
|
||||
import {
|
||||
ConfigNames,
|
||||
loadPoolConfig,
|
||||
getGenesisPoolAdmin,
|
||||
getEmergencyAdmin,
|
||||
} from '../../helpers/configuration';
|
||||
import {eEthereumNetwork} from '../../helpers/types';
|
||||
import {getLendingPoolAddressesProviderRegistry} from '../../helpers/contracts-getters';
|
||||
|
||||
|
@ -16,7 +21,7 @@ task(
|
|||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
|
||||
.setAction(async ({verify, pool}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
const network = <eEthereumNetwork>localBRE.network.name;
|
||||
const poolConfig = loadPoolConfig(pool);
|
||||
const {ProviderId} = poolConfig;
|
||||
|
@ -24,7 +29,11 @@ task(
|
|||
const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network);
|
||||
// Deploy address provider and set genesis manager
|
||||
const addressesProvider = await deployLendingPoolAddressesProvider(verify);
|
||||
await waitForTx(await addressesProvider.setAaveAdmin(await getGenesisAaveAdmin(poolConfig)));
|
||||
await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig)));
|
||||
const admin = await getEmergencyAdmin(poolConfig);
|
||||
console.log('Admin is ', admin);
|
||||
|
||||
await waitForTx(await addressesProvider.setEmergencyAdmin(admin));
|
||||
|
||||
// If no provider registry is set, deploy lending pool address provider registry and register the address provider
|
||||
const addressesProviderRegistry = !providerRegistryAddress
|
||||
|
@ -44,4 +53,12 @@ task(
|
|||
if (proxyProvider && proxyProvider !== '') {
|
||||
await waitForTx(await addressesProvider.setPriceOracle(proxyProvider));
|
||||
}
|
||||
|
||||
//register the lending rate oracle
|
||||
const lendingRateOracle = getParamPerNetwork(poolConfig.LendingRateOracle, network);
|
||||
|
||||
if (lendingRateOracle && lendingRateOracle !== '') {
|
||||
await waitForTx(await addressesProvider.setLendingRateOracle(proxyProvider));
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {insertContractAddressInDb} from '../../helpers/contracts-helpers';
|
||||
import {
|
||||
deployATokensAndRatesHelper,
|
||||
|
@ -17,7 +17,7 @@ import {
|
|||
task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {getParamPerNetwork} from '../../helpers/contracts-helpers';
|
||||
import {
|
||||
deployChainlinkProxyPriceProvider,
|
||||
|
@ -7,7 +7,7 @@ import {
|
|||
import {setInitialMarketRatesInRatesOracleByHelper} from '../../helpers/oracles-helpers';
|
||||
import {ICommonConfiguration, eEthereumNetwork, SymbolMap} from '../../helpers/types';
|
||||
import {waitForTx, filterMapBy} from '../../helpers/misc-utils';
|
||||
import {ConfigNames, loadPoolConfig} from '../../helpers/configuration';
|
||||
import {ConfigNames, loadPoolConfig, getWethAddress} from '../../helpers/configuration';
|
||||
import {exit} from 'process';
|
||||
import {
|
||||
getLendingPoolAddressesProvider,
|
||||
|
@ -19,22 +19,21 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment')
|
|||
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
|
||||
.setAction(async ({verify, pool}, localBRE) => {
|
||||
try {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
const network = <eEthereumNetwork>localBRE.network.name;
|
||||
const poolConfig = loadPoolConfig(pool);
|
||||
const {
|
||||
ProtocolGlobalParams: {UsdAddress},
|
||||
LendingRateOracleRatesCommon,
|
||||
ReserveAssets,
|
||||
ReserveSymbols,
|
||||
FallbackOracle,
|
||||
ChainlinkAggregator,
|
||||
} = poolConfig as ICommonConfiguration;
|
||||
const lendingRateOracles = filterMapBy(LendingRateOracleRatesCommon, (key) =>
|
||||
ReserveSymbols.includes(key)
|
||||
Object.keys(ReserveAssets[network]).includes(key)
|
||||
);
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
const admin = await addressesProvider.getAaveAdmin();
|
||||
const admin = await addressesProvider.getPoolAdmin();
|
||||
|
||||
const fallbackOracle = await getParamPerNetwork(FallbackOracle, network);
|
||||
const reserveAssets = await getParamPerNetwork(ReserveAssets, network);
|
||||
|
@ -47,7 +46,7 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment')
|
|||
const [tokens, aggregators] = getPairsTokenAggregator(tokensToWatch, chainlinkAggregators);
|
||||
|
||||
const chainlinkProviderPriceProvider = await deployChainlinkProxyPriceProvider(
|
||||
[tokens, aggregators, fallbackOracle],
|
||||
[tokens, aggregators, fallbackOracle, await getWethAddress(poolConfig)],
|
||||
verify
|
||||
);
|
||||
await waitForTx(
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {getParamPerNetwork} from '../../helpers/contracts-helpers';
|
||||
import {
|
||||
deployLendingPoolCollateralManager,
|
||||
deployWalletBalancerProvider,
|
||||
deployAaveProtocolTestHelpers,
|
||||
deployWETHGateway,
|
||||
} from '../../helpers/contracts-deployments';
|
||||
import {loadPoolConfig, ConfigNames} from '../../helpers/configuration';
|
||||
import {loadPoolConfig, ConfigNames, getWethAddress} from '../../helpers/configuration';
|
||||
import {eEthereumNetwork, ICommonConfiguration} from '../../helpers/types';
|
||||
import {waitForTx} from '../../helpers/misc-utils';
|
||||
import {
|
||||
|
@ -14,11 +15,7 @@ import {
|
|||
enableReservesAsCollateralByHelper,
|
||||
} from '../../helpers/init-helpers';
|
||||
import {exit} from 'process';
|
||||
import {
|
||||
getLendingPool,
|
||||
getLendingPoolConfiguratorProxy,
|
||||
getLendingPoolAddressesProvider,
|
||||
} from '../../helpers/contracts-getters';
|
||||
import {getLendingPoolAddressesProvider} from '../../helpers/contracts-getters';
|
||||
import {ZERO_ADDRESS} from '../../helpers/constants';
|
||||
|
||||
task('full:initialize-lending-pool', 'Initialize lending pool configuration.')
|
||||
|
@ -26,20 +23,18 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.')
|
|||
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
|
||||
.setAction(async ({verify, pool}, localBRE) => {
|
||||
try {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
const network = <eEthereumNetwork>localBRE.network.name;
|
||||
const poolConfig = loadPoolConfig(pool);
|
||||
const {ReserveAssets, ReservesConfig} = poolConfig as ICommonConfiguration;
|
||||
|
||||
const reserveAssets = await getParamPerNetwork(ReserveAssets, network);
|
||||
const lendingPoolProxy = await getLendingPool();
|
||||
const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy();
|
||||
|
||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||
|
||||
const testHelpers = await deployAaveProtocolTestHelpers(addressesProvider.address, verify);
|
||||
|
||||
const admin = await addressesProvider.getAaveAdmin();
|
||||
const admin = await addressesProvider.getPoolAdmin();
|
||||
if (!reserveAssets) {
|
||||
throw 'Reserve assets is undefined. Check ReserveAssets configuration at config directory';
|
||||
}
|
||||
|
@ -54,6 +49,11 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.')
|
|||
);
|
||||
|
||||
await deployWalletBalancerProvider(addressesProvider.address, verify);
|
||||
|
||||
const wethAddress = await getWethAddress(poolConfig);
|
||||
const lendingPoolAddress = await addressesProvider.getLendingPool();
|
||||
|
||||
await deployWETHGateway([wethAddress, lendingPoolAddress]);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
exit(1);
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {checkVerification} from '../../helpers/etherscan-verification';
|
||||
import {ConfigNames} from '../../helpers/configuration';
|
||||
import {printContracts} from '../../helpers/misc-utils';
|
||||
|
||||
task('aave:dev', 'Deploy development enviroment')
|
||||
.addOptionalParam('verify', 'Verify contracts at Etherscan')
|
||||
.setAction(async ({verify}, localBRE) => {
|
||||
const POOL_NAME = ConfigNames.Aave;
|
||||
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
// Prevent loss of gas verifying all the needed ENVs for Etherscan verification
|
||||
if (verify) {
|
||||
|
@ -29,7 +30,8 @@ task('aave:dev', 'Deploy development enviroment')
|
|||
await localBRE.run('dev:deploy-oracles', {verify, pool: POOL_NAME});
|
||||
|
||||
console.log('5. Initialize lending pool');
|
||||
await localBRE.run('dev:initialize-lending-pool', {verify});
|
||||
await localBRE.run('dev:initialize-lending-pool', {verify, pool: POOL_NAME});
|
||||
|
||||
console.log('\nFinished migration');
|
||||
printContracts();
|
||||
});
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {checkVerification} from '../../helpers/etherscan-verification';
|
||||
import {ConfigNames} from '../../helpers/configuration';
|
||||
import {EthereumNetworkNames} from '../../helpers/types';
|
||||
import {printContracts} from '../../helpers/misc-utils';
|
||||
|
||||
task('aave:full', 'Deploy development enviroment')
|
||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||
|
@ -9,7 +10,7 @@ task('aave:full', 'Deploy development enviroment')
|
|||
const POOL_NAME = ConfigNames.Aave;
|
||||
const network = <EthereumNetworkNames>localBRE.network.name;
|
||||
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
// Prevent loss of gas verifying all the needed ENVs for Etherscan verification
|
||||
if (verify) {
|
||||
|
@ -28,4 +29,5 @@ task('aave:full', 'Deploy development enviroment')
|
|||
await localBRE.run('full:initialize-lending-pool', {verify, pool: POOL_NAME});
|
||||
|
||||
console.log('\nFinished migrations');
|
||||
printContracts();
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {checkVerification} from '../../helpers/etherscan-verification';
|
||||
import {ConfigNames} from '../../helpers/configuration';
|
||||
|
||||
|
@ -7,7 +7,7 @@ task('uniswap:dev', 'Deploy development enviroment')
|
|||
.setAction(async ({verify}, localBRE) => {
|
||||
const POOL_NAME = ConfigNames.Uniswap;
|
||||
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
// Prevent loss of gas verifying all the needed ENVs for Etherscan verification
|
||||
if (verify) {
|
||||
|
@ -29,7 +29,7 @@ task('uniswap:dev', 'Deploy development enviroment')
|
|||
await localBRE.run('dev:deploy-oracles', {verify, pool: POOL_NAME});
|
||||
|
||||
console.log('5. Initialize lending pool');
|
||||
await localBRE.run('dev:initialize-lending-pool', {verify});
|
||||
await localBRE.run('dev:initialize-lending-pool', {verify, pool: POOL_NAME});
|
||||
|
||||
console.log('\nFinished migration');
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {checkVerification} from '../../helpers/etherscan-verification';
|
||||
import {ConfigNames} from '../../helpers/configuration';
|
||||
|
||||
|
@ -7,7 +7,7 @@ task('uniswap:full', 'Deploy development enviroment')
|
|||
.setAction(async ({verify}, localBRE) => {
|
||||
const POOL_NAME = ConfigNames.Uniswap;
|
||||
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
// Prevent loss of gas verifying all the needed ENVs for Etherscan verification
|
||||
if (verify) {
|
||||
|
|
9
tasks/misc/print-contracts.ts
Normal file
9
tasks/misc/print-contracts.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import {task} from 'hardhat/config';
|
||||
import {printContracts} from '../../helpers/misc-utils';
|
||||
|
||||
task('print-contracts', 'Inits the DRE, to have access to all the plugins').setAction(
|
||||
async ({}, localBRE) => {
|
||||
await localBRE.run('set-DRE');
|
||||
printContracts();
|
||||
}
|
||||
);
|
|
@ -1,9 +1,9 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {setBRE} from '../../helpers/misc-utils';
|
||||
import {task} from 'hardhat/config';
|
||||
import {setDRE} from '../../helpers/misc-utils';
|
||||
|
||||
task(`set-bre`, `Inits the BRE, to have access to all the plugins' objects`).setAction(
|
||||
async (_, _BRE) => {
|
||||
setBRE(_BRE);
|
||||
return _BRE;
|
||||
task(`set-DRE`, `Inits the DRE, to have access to all the plugins' objects`).setAction(
|
||||
async (_, _DRE) => {
|
||||
setDRE(_DRE);
|
||||
return _DRE;
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {task} from '@nomiclabs/buidler/config';
|
||||
import {task} from 'hardhat/config';
|
||||
import {verifyContract, checkVerification} from '../../helpers/etherscan-verification';
|
||||
|
||||
interface VerifyParams {
|
||||
|
@ -8,7 +8,7 @@ interface VerifyParams {
|
|||
libraries: string;
|
||||
}
|
||||
|
||||
task('verify-sc', 'Inits the BRE, to have access to all the plugins')
|
||||
task('verify-sc', 'Inits the DRE, to have access to all the plugins')
|
||||
.addParam('contractName', 'Name of the Solidity smart contract')
|
||||
.addParam('address', 'Ethereum address of the smart contract')
|
||||
.addOptionalParam(
|
||||
|
@ -25,7 +25,7 @@ task('verify-sc', 'Inits the BRE, to have access to all the plugins')
|
|||
{contractName, address, constructorArguments = [], libraries}: VerifyParams,
|
||||
localBRE
|
||||
) => {
|
||||
await localBRE.run('set-bre');
|
||||
await localBRE.run('set-DRE');
|
||||
|
||||
checkVerification();
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import rawBRE from '@nomiclabs/buidler';
|
||||
import rawBRE from 'hardhat';
|
||||
import {MockContract} from 'ethereum-waffle';
|
||||
import {
|
||||
insertContractAddressInDb,
|
||||
|
@ -20,6 +20,8 @@ import {
|
|||
deployLendingRateOracle,
|
||||
deployStableAndVariableTokensHelper,
|
||||
deployATokensAndRatesHelper,
|
||||
deployWETHGateway,
|
||||
deployWETHMocked,
|
||||
deployMockUniswapRouter,
|
||||
deployUniswapLiquiditySwapAdapter,
|
||||
deployUniswapRepayAdapter,
|
||||
|
@ -27,7 +29,7 @@ import {
|
|||
import {Signer} from 'ethers';
|
||||
import {TokenContractId, eContractid, tEthereumAddress, AavePools} from '../helpers/types';
|
||||
import {MintableErc20 as MintableERC20} from '../types/MintableErc20';
|
||||
import {getReservesConfigByPool} from '../helpers/configuration';
|
||||
import {getEmergencyAdmin, getReservesConfigByPool} from '../helpers/configuration';
|
||||
import {initializeMakeSuite} from './helpers/make-suite';
|
||||
|
||||
import {
|
||||
|
@ -35,7 +37,7 @@ import {
|
|||
deployAllMockAggregators,
|
||||
setInitialMarketRatesInRatesOracleByHelper,
|
||||
} from '../helpers/oracles-helpers';
|
||||
import {waitForTx} from '../helpers/misc-utils';
|
||||
import {DRE, waitForTx} from '../helpers/misc-utils';
|
||||
import {
|
||||
initReservesByHelper,
|
||||
enableReservesToBorrowByHelper,
|
||||
|
@ -48,6 +50,7 @@ import {
|
|||
getLendingPoolConfiguratorProxy,
|
||||
getPairsTokenAggregator,
|
||||
} from '../helpers/contracts-getters';
|
||||
import {Weth9Mocked} from '../types/Weth9Mocked';
|
||||
|
||||
const MOCK_USD_PRICE_IN_WEI = AaveConfig.ProtocolGlobalParams.MockUsdPriceInWei;
|
||||
const ALL_ASSETS_INITIAL_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices;
|
||||
|
@ -56,12 +59,17 @@ const MOCK_CHAINLINK_AGGREGATORS_PRICES = AaveConfig.Mocks.ChainlinkAggregatorPr
|
|||
const LENDING_RATE_ORACLE_RATES_COMMON = AaveConfig.LendingRateOracleRatesCommon;
|
||||
|
||||
const deployAllMockTokens = async (deployer: Signer) => {
|
||||
const tokens: {[symbol: string]: MockContract | MintableERC20} = {};
|
||||
const tokens: {[symbol: string]: MockContract | MintableERC20 | Weth9Mocked} = {};
|
||||
|
||||
const protoConfigData = getReservesConfigByPool(AavePools.proto);
|
||||
const secondaryConfigData = getReservesConfigByPool(AavePools.secondary);
|
||||
|
||||
for (const tokenSymbol of Object.keys(TokenContractId)) {
|
||||
if (tokenSymbol === 'WETH') {
|
||||
tokens[tokenSymbol] = await deployWETHMocked();
|
||||
await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]);
|
||||
continue;
|
||||
}
|
||||
let decimals = 18;
|
||||
|
||||
let configData = (<any>protoConfigData)[tokenSymbol];
|
||||
|
@ -90,9 +98,20 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
const aaveAdmin = await deployer.getAddress();
|
||||
|
||||
const mockTokens = await deployAllMockTokens(deployer);
|
||||
const mockTokenAddress = Object.keys(mockTokens).reduce<{[key: string]: string}>((acc, key) => {
|
||||
acc[key] = mockTokens[key].address;
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
const addressesProvider = await deployLendingPoolAddressesProvider();
|
||||
await waitForTx(await addressesProvider.setAaveAdmin(aaveAdmin));
|
||||
await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin));
|
||||
|
||||
//setting users[1] as emergency admin, which is in position 2 in the DRE addresses list
|
||||
const addressList = await Promise.all(
|
||||
(await DRE.ethers.getSigners()).map((signer) => signer.getAddress())
|
||||
);
|
||||
|
||||
await waitForTx(await addressesProvider.setEmergencyAdmin(addressList[2]));
|
||||
|
||||
const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry();
|
||||
await waitForTx(
|
||||
|
@ -103,8 +122,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
|
||||
await waitForTx(await addressesProvider.setLendingPoolImpl(lendingPoolImpl.address));
|
||||
|
||||
const address = await addressesProvider.getLendingPool();
|
||||
const lendingPoolProxy = await getLendingPool(address);
|
||||
const lendingPoolAddress = await addressesProvider.getLendingPool();
|
||||
const lendingPoolProxy = await getLendingPool(lendingPoolAddress);
|
||||
|
||||
await insertContractAddressInDb(eContractid.LendingPool, lendingPoolProxy.address);
|
||||
|
||||
|
@ -139,7 +158,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
USDC: mockTokens.USDC.address,
|
||||
USDT: mockTokens.USDT.address,
|
||||
SUSD: mockTokens.SUSD.address,
|
||||
LEND: mockTokens.LEND.address,
|
||||
AAVE: mockTokens.AAVE.address,
|
||||
BAT: mockTokens.BAT.address,
|
||||
REP: mockTokens.REP.address,
|
||||
MKR: mockTokens.MKR.address,
|
||||
|
@ -150,7 +169,10 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
ZRX: mockTokens.ZRX.address,
|
||||
SNX: mockTokens.SNX.address,
|
||||
BUSD: mockTokens.BUSD.address,
|
||||
|
||||
YFI: mockTokens.BUSD.address,
|
||||
REN: mockTokens.REN.address,
|
||||
UNI: mockTokens.UNI.address,
|
||||
ENJ: mockTokens.ENJ.address,
|
||||
USD: USD_ADDRESS,
|
||||
|
||||
UNI_DAI_ETH: mockTokens.UNI_DAI_ETH.address,
|
||||
|
@ -186,6 +208,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
tokens,
|
||||
aggregators,
|
||||
fallbackOracle.address,
|
||||
mockTokens.WETH.address,
|
||||
]);
|
||||
await waitForTx(await addressesProvider.setPriceOracle(fallbackOracle.address));
|
||||
|
||||
|
@ -263,11 +286,13 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
|||
|
||||
await deployWalletBalancerProvider(addressesProvider.address);
|
||||
|
||||
await deployWETHGateway([mockTokens.WETH.address, lendingPoolAddress]);
|
||||
|
||||
console.timeEnd('setup');
|
||||
};
|
||||
|
||||
before(async () => {
|
||||
await rawBRE.run('set-bre');
|
||||
await rawBRE.run('set-DRE');
|
||||
const [deployer, secondaryWallet] = await getEthersSigners();
|
||||
console.log('-> Deploying test environment...');
|
||||
await buildTestEnv(deployer, secondaryWallet);
|
||||
|
|
|
@ -5,7 +5,7 @@ import {expect} from 'chai';
|
|||
import {ethers} from 'ethers';
|
||||
import {eEthereumNetwork} from '../helpers/types';
|
||||
import {makeSuite, TestEnv} from './helpers/make-suite';
|
||||
import {BRE} from '../helpers/misc-utils';
|
||||
import {DRE} from '../helpers/misc-utils';
|
||||
import {
|
||||
ConfigNames,
|
||||
getATokenDomainSeparatorPerNetwork,
|
||||
|
@ -47,7 +47,7 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|||
|
||||
const tokenName = await aDai.name();
|
||||
|
||||
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const expiration = 0;
|
||||
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
||||
const permitAmount = ethers.utils.parseEther('2').toString();
|
||||
|
@ -92,7 +92,7 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|||
const owner = deployer;
|
||||
const spender = users[1];
|
||||
|
||||
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const deadline = MAX_UINT_AMOUNT;
|
||||
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
||||
const permitAmount = parseEther('2').toString();
|
||||
|
@ -134,7 +134,7 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|||
const owner = deployer;
|
||||
const spender = users[1];
|
||||
|
||||
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const deadline = MAX_UINT_AMOUNT;
|
||||
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
||||
const permitAmount = '0';
|
||||
|
@ -180,7 +180,7 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|||
const owner = deployer;
|
||||
const spender = users[1];
|
||||
|
||||
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const deadline = MAX_UINT_AMOUNT;
|
||||
const nonce = 1000;
|
||||
const permitAmount = '0';
|
||||
|
@ -215,7 +215,7 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|||
const owner = deployer;
|
||||
const spender = users[1];
|
||||
|
||||
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const expiration = '1';
|
||||
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
||||
const permitAmount = '0';
|
||||
|
@ -250,7 +250,7 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|||
const owner = deployer;
|
||||
const spender = users[1];
|
||||
|
||||
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const deadline = MAX_UINT_AMOUNT;
|
||||
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
||||
const permitAmount = '0';
|
||||
|
@ -285,7 +285,7 @@ makeSuite('AToken: Permit', (testEnv: TestEnv) => {
|
|||
const owner = deployer;
|
||||
const spender = users[1];
|
||||
|
||||
const chainId = BRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const chainId = DRE.network.config.chainId || BUIDLEREVM_CHAINID;
|
||||
const expiration = MAX_UINT_AMOUNT;
|
||||
const nonce = (await aDai._nonces(owner.address)).toNumber();
|
||||
const permitAmount = '0';
|
||||
|
|
|
@ -11,7 +11,7 @@ const {expect} = require('chai');
|
|||
|
||||
makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
||||
const {
|
||||
LPC_CALLER_NOT_AAVE_ADMIN,
|
||||
CALLER_NOT_POOL_ADMIN,
|
||||
LPC_RESERVE_LIQUIDITY_NOT_0,
|
||||
RC_INVALID_LTV,
|
||||
RC_INVALID_LIQ_THRESHOLD,
|
||||
|
@ -87,16 +87,16 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).deactivateReserve(weth.address),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Check the onlyAaveAdmin on activateReserve ', async () => {
|
||||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).activateReserve(weth.address),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Freezes the ETH reserve', async () => {
|
||||
|
@ -156,16 +156,16 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).freezeReserve(weth.address),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Check the onlyAaveAdmin on unfreezeReserve ', async () => {
|
||||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).unfreezeReserve(weth.address),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Deactivates the ETH reserve for borrowing', async () => {
|
||||
|
@ -228,21 +228,22 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).disableBorrowingOnReserve(weth.address),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => {
|
||||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Deactivates the ETH reserve as collateral', async () => {
|
||||
const {configurator, helpersContract, weth} = testEnv;
|
||||
await configurator.disableReserveAsCollateral(weth.address);
|
||||
await configurator.configureReserveAsCollateral(weth.address, 0, 0, 0);
|
||||
|
||||
const {
|
||||
decimals,
|
||||
ltv,
|
||||
|
@ -260,15 +261,15 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
expect(isFrozen).to.be.equal(false);
|
||||
expect(decimals).to.be.equal(18);
|
||||
expect(ltv).to.be.equal(0);
|
||||
expect(liquidationThreshold).to.be.equal(8000);
|
||||
expect(liquidationBonus).to.be.equal(10500);
|
||||
expect(liquidationThreshold).to.be.equal(0);
|
||||
expect(liquidationBonus).to.be.equal(0);
|
||||
expect(stableBorrowRateEnabled).to.be.equal(true);
|
||||
expect(reserveFactor).to.be.equal(0);
|
||||
});
|
||||
|
||||
it('Activates the ETH reserve as collateral', async () => {
|
||||
const {configurator, helpersContract, weth} = testEnv;
|
||||
await configurator.enableReserveAsCollateral(weth.address, '7500', '8000', '10500');
|
||||
await configurator.configureReserveAsCollateral(weth.address, '7500', '8000', '10500');
|
||||
|
||||
const {
|
||||
decimals,
|
||||
|
@ -293,22 +294,14 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
expect(reserveFactor).to.be.equal(0);
|
||||
});
|
||||
|
||||
it('Check the onlyAaveAdmin on disableReserveAsCollateral ', async () => {
|
||||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).disableReserveAsCollateral(weth.address),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
});
|
||||
|
||||
it('Check the onlyAaveAdmin on enableReserveAsCollateral ', async () => {
|
||||
it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => {
|
||||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator
|
||||
.connect(users[2].signer)
|
||||
.enableReserveAsCollateral(weth.address, '75', '80', '105'),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
.configureReserveAsCollateral(weth.address, '7500', '8000', '10500'),
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Disable stable borrow rate on the ETH reserve', async () => {
|
||||
|
@ -367,16 +360,16 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).disableReserveStableRate(weth.address),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Check the onlyAaveAdmin on enableReserveStableRate', async () => {
|
||||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).enableReserveStableRate(weth.address),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Changes LTV of the reserve', async () => {
|
||||
|
@ -409,8 +402,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).setLtv(weth.address, '75'),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Changes the reserve factor of the reserve', async () => {
|
||||
|
@ -443,8 +436,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).setReserveFactor(weth.address, '2000'),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Changes liquidation threshold of the reserve', async () => {
|
||||
|
@ -477,8 +470,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).setLiquidationThreshold(weth.address, '80'),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Changes liquidation bonus of the reserve', async () => {
|
||||
|
@ -511,24 +504,24 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).setLiquidationBonus(weth.address, '80'),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Check the onlyAaveAdmin on setReserveDecimals', async () => {
|
||||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).setReserveDecimals(weth.address, '80'),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Check the onlyAaveAdmin on setLiquidationBonus', async () => {
|
||||
const {configurator, users, weth} = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).setLiquidationBonus(weth.address, '80'),
|
||||
LPC_CALLER_NOT_AAVE_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => {
|
||||
|
|
58
test/delegation-aware-atoken.spec.ts
Normal file
58
test/delegation-aware-atoken.spec.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import {MAX_UINT_AMOUNT, ZERO_ADDRESS} from '../helpers/constants';
|
||||
import {BUIDLEREVM_CHAINID} from '../helpers/buidler-constants';
|
||||
import {buildPermitParams, getSignatureFromTypedData} from '../helpers/contracts-helpers';
|
||||
import {expect} from 'chai';
|
||||
import {ethers} from 'ethers';
|
||||
import {eEthereumNetwork, ProtocolErrors} from '../helpers/types';
|
||||
import {makeSuite, TestEnv} from './helpers/make-suite';
|
||||
import {DRE} from '../helpers/misc-utils';
|
||||
import {
|
||||
ConfigNames,
|
||||
getATokenDomainSeparatorPerNetwork,
|
||||
loadPoolConfig,
|
||||
} from '../helpers/configuration';
|
||||
import {waitForTx} from '../helpers/misc-utils';
|
||||
import {
|
||||
deployDelegationAwareAToken,
|
||||
deployMintableDelegationERC20,
|
||||
} from '../helpers/contracts-deployments';
|
||||
import {DelegationAwareATokenFactory} from '../types';
|
||||
import {DelegationAwareAToken} from '../types/DelegationAwareAToken';
|
||||
import {MintableDelegationErc20} from '../types/MintableDelegationErc20';
|
||||
|
||||
const {parseEther} = ethers.utils;
|
||||
|
||||
makeSuite('AToken: underlying delegation', (testEnv: TestEnv) => {
|
||||
const poolConfig = loadPoolConfig(ConfigNames.Commons);
|
||||
let delegationAToken = <DelegationAwareAToken>{};
|
||||
let delegationERC20 = <MintableDelegationErc20>{};
|
||||
|
||||
it('Deploys a new MintableDelegationERC20 and a DelegationAwareAToken', async () => {
|
||||
const {pool} = testEnv;
|
||||
|
||||
delegationERC20 = await deployMintableDelegationERC20(['DEL', 'DEL', '18']);
|
||||
|
||||
delegationAToken = await deployDelegationAwareAToken(
|
||||
[pool.address, delegationERC20.address, 'aDEL', 'aDEL', ZERO_ADDRESS],
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it('Tries to delegate with the caller not being the Aave admin', async () => {
|
||||
const {users} = testEnv;
|
||||
|
||||
await expect(
|
||||
delegationAToken.connect(users[1].signer).delegateUnderlyingTo(users[2].address)
|
||||
).to.be.revertedWith(ProtocolErrors.CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Tries to delegate to user 2', async () => {
|
||||
const {users} = testEnv;
|
||||
|
||||
await delegationAToken.delegateUnderlyingTo(users[2].address);
|
||||
|
||||
const delegateeAddress = await delegationERC20.delegatee();
|
||||
|
||||
expect(delegateeAddress).to.be.equal(users[2].address);
|
||||
});
|
||||
});
|
|
@ -24,7 +24,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
LP_INVALID_FLASHLOAN_MODE,
|
||||
SAFEERC20_LOWLEVEL_CALL,
|
||||
LP_INVALID_FLASH_LOAN_EXECUTOR_RETURN,
|
||||
LP_BORROW_ALLOWANCE_ARE_NOT_ENOUGH,
|
||||
LP_BORROW_ALLOWANCE_NOT_ENOUGH,
|
||||
} = ProtocolErrors;
|
||||
|
||||
before(async () => {
|
||||
|
@ -443,7 +443,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
'0x10',
|
||||
'0'
|
||||
)
|
||||
).to.be.revertedWith(LP_BORROW_ALLOWANCE_ARE_NOT_ENOUGH);
|
||||
).to.be.revertedWith(LP_BORROW_ALLOWANCE_NOT_ENOUGH);
|
||||
});
|
||||
|
||||
it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user with allowance. A loan for onBehalfOf is creatd.', async () => {
|
||||
|
@ -454,10 +454,12 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
|||
|
||||
const flashAmount = ethers.utils.parseEther('0.8');
|
||||
|
||||
const reserveData = await pool.getReserveData(weth.address);
|
||||
|
||||
const stableDebtToken = await getVariableDebtToken(reserveData.stableDebtTokenAddress);
|
||||
|
||||
// Deposited for onBehalfOf user already, delegate borrow allowance
|
||||
await pool
|
||||
.connect(onBehalfOf.signer)
|
||||
.delegateBorrowAllowance([weth.address], caller.address, [1], [flashAmount]);
|
||||
await stableDebtToken.connect(onBehalfOf.signer).approveDelegation(caller.address, flashAmount);
|
||||
|
||||
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||
|
||||
|
|
|
@ -18,10 +18,15 @@ import {
|
|||
import {getReserveAddressFromSymbol, getReserveData, getUserData} from './utils/helpers';
|
||||
|
||||
import {convertToCurrencyDecimals} from '../../helpers/contracts-helpers';
|
||||
import {getAToken, getMintableErc20} from '../../helpers/contracts-getters';
|
||||
import {
|
||||
getAToken,
|
||||
getMintableErc20,
|
||||
getStableDebtToken,
|
||||
getVariableDebtToken,
|
||||
} from '../../helpers/contracts-getters';
|
||||
import {MAX_UINT_AMOUNT, ONE_YEAR} from '../../helpers/constants';
|
||||
import {SignerWithAddress, TestEnv} from './make-suite';
|
||||
import {BRE, increaseTime, timeLatest, waitForTx} from '../../helpers/misc-utils';
|
||||
import {DRE, increaseTime, timeLatest, waitForTx} from '../../helpers/misc-utils';
|
||||
|
||||
import chai from 'chai';
|
||||
import {ReserveData, UserReserveData} from './utils/interfaces';
|
||||
|
@ -277,9 +282,9 @@ export const withdraw = async (
|
|||
};
|
||||
|
||||
export const delegateBorrowAllowance = async (
|
||||
reserveSymbols: string[],
|
||||
amounts: string[],
|
||||
interestRateModes: string[],
|
||||
reserve: string,
|
||||
amount: string,
|
||||
interestRateMode: string,
|
||||
user: SignerWithAddress,
|
||||
receiver: tEthereumAddress,
|
||||
expectedResult: string,
|
||||
|
@ -288,32 +293,33 @@ export const delegateBorrowAllowance = async (
|
|||
) => {
|
||||
const {pool} = testEnv;
|
||||
|
||||
const reserves: tEthereumAddress[] = [];
|
||||
const amountsToDelegate: tEthereumAddress[] = [];
|
||||
for (const reserveSymbol of reserveSymbols) {
|
||||
const newLength = reserves.push(await getReserveAddressFromSymbol(reserveSymbol));
|
||||
amountsToDelegate.push(
|
||||
await (
|
||||
await convertToCurrencyDecimals(reserves[newLength - 1], amounts[newLength - 1])
|
||||
).toString()
|
||||
);
|
||||
}
|
||||
const reserveAddress: tEthereumAddress = await getReserveAddressFromSymbol(reserve);
|
||||
|
||||
const delegateAllowancePromise = pool
|
||||
const amountToDelegate: string = await (
|
||||
await convertToCurrencyDecimals(reserveAddress, amount)
|
||||
).toString();
|
||||
|
||||
const reserveData = await pool.getReserveData(reserveAddress);
|
||||
|
||||
const debtToken =
|
||||
interestRateMode === '1'
|
||||
? await getStableDebtToken(reserveData.stableDebtTokenAddress)
|
||||
: await getVariableDebtToken(reserveData.variableDebtTokenAddress);
|
||||
|
||||
const delegateAllowancePromise = debtToken
|
||||
.connect(user.signer)
|
||||
.delegateBorrowAllowance(reserves, receiver, interestRateModes, amountsToDelegate);
|
||||
if (expectedResult === 'revert') {
|
||||
await expect(delegateAllowancePromise, revertMessage).to.be.reverted;
|
||||
.approveDelegation(receiver, amountToDelegate);
|
||||
|
||||
if (expectedResult === 'revert' && revertMessage) {
|
||||
await expect(delegateAllowancePromise, revertMessage).to.be.revertedWith(revertMessage);
|
||||
return;
|
||||
} else {
|
||||
await delegateAllowancePromise;
|
||||
for (const [i, reserve] of reserves.entries()) {
|
||||
expect(
|
||||
(
|
||||
await pool.getBorrowAllowance(user.address, receiver, reserve, interestRateModes[i])
|
||||
).toString()
|
||||
).to.be.equal(amountsToDelegate[i], 'borrowAllowance are set incorrectly');
|
||||
}
|
||||
const allowance = await debtToken.borrowAllowance(user.address, receiver);
|
||||
expect(allowance.toString()).to.be.equal(
|
||||
amountToDelegate,
|
||||
'borrowAllowance is set incorrectly'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -729,9 +735,9 @@ export const getTxCostAndTimestamp = async (tx: ContractReceipt) => {
|
|||
if (!tx.blockNumber || !tx.transactionHash || !tx.cumulativeGasUsed) {
|
||||
throw new Error('No tx blocknumber');
|
||||
}
|
||||
const txTimestamp = new BigNumber((await BRE.ethers.provider.getBlock(tx.blockNumber)).timestamp);
|
||||
const txTimestamp = new BigNumber((await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp);
|
||||
|
||||
const txInfo = await BRE.ethers.provider.getTransaction(tx.transactionHash);
|
||||
const txInfo = await DRE.ethers.provider.getTransaction(tx.transactionHash);
|
||||
const txCost = new BigNumber(tx.cumulativeGasUsed.toString()).multipliedBy(
|
||||
txInfo.gasPrice.toString()
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {evmRevert, evmSnapshot, BRE} from '../../helpers/misc-utils';
|
||||
import {evmRevert, evmSnapshot, DRE} from '../../helpers/misc-utils';
|
||||
import {Signer} from 'ethers';
|
||||
import {
|
||||
getLendingPool,
|
||||
|
@ -9,6 +9,8 @@ import {
|
|||
getLendingPoolConfiguratorProxy,
|
||||
getPriceOracle,
|
||||
getLendingPoolAddressesProviderRegistry,
|
||||
getWETHMocked,
|
||||
getWETHGateway,
|
||||
getUniswapLiquiditySwapAdapter,
|
||||
getUniswapRepayAdapter,
|
||||
} from '../../helpers/contracts-getters';
|
||||
|
@ -29,8 +31,13 @@ import {LendingPoolAddressesProviderRegistry} from '../../types/LendingPoolAddre
|
|||
import {getEthersSigners} from '../../helpers/contracts-helpers';
|
||||
import {UniswapLiquiditySwapAdapter} from '../../types/UniswapLiquiditySwapAdapter';
|
||||
import {UniswapRepayAdapter} from '../../types/UniswapRepayAdapter';
|
||||
import {Weth9Mocked} from '../../types/Weth9Mocked';
|
||||
import {WethGateway} from '../../types/WethGateway';
|
||||
import {solidity} from 'ethereum-waffle';
|
||||
|
||||
chai.use(bignumberChai());
|
||||
chai.use(almostEqual());
|
||||
chai.use(solidity);
|
||||
|
||||
export interface SignerWithAddress {
|
||||
signer: Signer;
|
||||
|
@ -43,21 +50,22 @@ export interface TestEnv {
|
|||
configurator: LendingPoolConfigurator;
|
||||
oracle: PriceOracle;
|
||||
helpersContract: AaveProtocolTestHelpers;
|
||||
weth: MintableERC20;
|
||||
weth: Weth9Mocked;
|
||||
aWETH: AToken;
|
||||
dai: MintableERC20;
|
||||
aDai: AToken;
|
||||
usdc: MintableERC20;
|
||||
lend: MintableERC20;
|
||||
aave: MintableERC20;
|
||||
addressesProvider: LendingPoolAddressesProvider;
|
||||
uniswapLiquiditySwapAdapter: UniswapLiquiditySwapAdapter;
|
||||
uniswapRepayAdapter: UniswapRepayAdapter;
|
||||
registry: LendingPoolAddressesProviderRegistry;
|
||||
wethGateway: WethGateway;
|
||||
}
|
||||
|
||||
let buidlerevmSnapshotId: string = '0x1';
|
||||
const setBuidlerevmSnapshotId = (id: string) => {
|
||||
if (BRE.network.name === 'buidlerevm') {
|
||||
if (DRE.network.name === 'hardhat') {
|
||||
buidlerevmSnapshotId = id;
|
||||
}
|
||||
};
|
||||
|
@ -69,16 +77,17 @@ const testEnv: TestEnv = {
|
|||
configurator: {} as LendingPoolConfigurator,
|
||||
helpersContract: {} as AaveProtocolTestHelpers,
|
||||
oracle: {} as PriceOracle,
|
||||
weth: {} as MintableERC20,
|
||||
weth: {} as Weth9Mocked,
|
||||
aWETH: {} as AToken,
|
||||
dai: {} as MintableERC20,
|
||||
aDai: {} as AToken,
|
||||
usdc: {} as MintableERC20,
|
||||
lend: {} as MintableERC20,
|
||||
aave: {} as MintableERC20,
|
||||
addressesProvider: {} as LendingPoolAddressesProvider,
|
||||
uniswapLiquiditySwapAdapter: {} as UniswapLiquiditySwapAdapter,
|
||||
uniswapRepayAdapter: {} as UniswapRepayAdapter,
|
||||
registry: {} as LendingPoolAddressesProviderRegistry,
|
||||
wethGateway: {} as WethGateway,
|
||||
} as TestEnv;
|
||||
|
||||
export async function initializeMakeSuite() {
|
||||
|
@ -115,14 +124,14 @@ export async function initializeMakeSuite() {
|
|||
|
||||
const daiAddress = reservesTokens.find((token) => token.symbol === 'DAI')?.tokenAddress;
|
||||
const usdcAddress = reservesTokens.find((token) => token.symbol === 'USDC')?.tokenAddress;
|
||||
const lendAddress = reservesTokens.find((token) => token.symbol === 'LEND')?.tokenAddress;
|
||||
const aaveAddress = reservesTokens.find((token) => token.symbol === 'AAVE')?.tokenAddress;
|
||||
const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress;
|
||||
|
||||
if (!aDaiAddress || !aWEthAddress) {
|
||||
console.log(`atoken-modifiers.spec: aTokens not correctly initialized`);
|
||||
process.exit(1);
|
||||
}
|
||||
if (!daiAddress || !usdcAddress || !lendAddress || !wethAddress) {
|
||||
if (!daiAddress || !usdcAddress || !aaveAddress || !wethAddress) {
|
||||
console.log(`atoken-modifiers.spec: USDC or DAI not correctly initialized`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
@ -132,8 +141,9 @@ export async function initializeMakeSuite() {
|
|||
|
||||
testEnv.dai = await getMintableErc20(daiAddress);
|
||||
testEnv.usdc = await getMintableErc20(usdcAddress);
|
||||
testEnv.lend = await getMintableErc20(lendAddress);
|
||||
testEnv.weth = await getMintableErc20(wethAddress);
|
||||
testEnv.aave = await getMintableErc20(aaveAddress);
|
||||
testEnv.weth = await getWETHMocked(wethAddress);
|
||||
testEnv.wethGateway = await getWETHGateway();
|
||||
|
||||
testEnv.uniswapLiquiditySwapAdapter = await getUniswapLiquiditySwapAdapter();
|
||||
testEnv.uniswapRepayAdapter = await getUniswapRepayAdapter();
|
||||
|
|
|
@ -121,9 +121,9 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv
|
|||
}
|
||||
|
||||
await delegateBorrowAllowance(
|
||||
[reserve],
|
||||
[amount],
|
||||
[rateMode],
|
||||
reserve,
|
||||
amount,
|
||||
rateMode,
|
||||
user,
|
||||
toUser,
|
||||
expected,
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
"borrowRateMode": "stable"
|
||||
},
|
||||
"expected": "revert",
|
||||
"revertMessage": "54"
|
||||
"revertMessage": "59"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -96,7 +96,7 @@
|
|||
"borrowRateMode": "variable"
|
||||
},
|
||||
"expected": "revert",
|
||||
"revertMessage": "54"
|
||||
"revertMessage": "59"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -126,23 +126,6 @@
|
|||
"expected": "success"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "User 0 delegates borrowing of 1 WETH to user 2 with wrong borrowRateMode, revert expected",
|
||||
"actions": [
|
||||
{
|
||||
"name": "delegateBorrowAllowance",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
"amount": "1",
|
||||
"user": "0",
|
||||
"borrowRateMode": "random",
|
||||
"toUser": "2"
|
||||
},
|
||||
"expected": "revert",
|
||||
"revertMessage": "8"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -136,13 +136,13 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"description": "User 1 Deposits 1000 LEND, disables WETH as collateral. Should revert as 1000 LEND are not enough to cover the debt (revert expected)",
|
||||
"description": "User 1 Deposits 1000 AAVE, disables WETH as collateral. Should revert as 1000 AAVE are not enough to cover the debt (revert expected)",
|
||||
"actions": [
|
||||
{
|
||||
"name": "mint",
|
||||
"args": {
|
||||
"reserve": "LEND",
|
||||
"amount": "1000",
|
||||
"reserve": "AAVE",
|
||||
"amount": "10",
|
||||
"user": "1"
|
||||
},
|
||||
"expected": "success"
|
||||
|
@ -150,7 +150,7 @@
|
|||
{
|
||||
"name": "approve",
|
||||
"args": {
|
||||
"reserve": "LEND",
|
||||
"reserve": "AAVE",
|
||||
"user": "1"
|
||||
},
|
||||
"expected": "success"
|
||||
|
@ -158,9 +158,9 @@
|
|||
{
|
||||
"name": "deposit",
|
||||
"args": {
|
||||
"reserve": "LEND",
|
||||
"reserve": "AAVE",
|
||||
|
||||
"amount": "1000",
|
||||
"amount": "10",
|
||||
"user": "1"
|
||||
},
|
||||
"expected": "success"
|
||||
|
@ -178,13 +178,13 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"description": "User 1 Deposits 64000 more LEND (enough to cover the DAI debt), disables WETH as collateral",
|
||||
"description": "User 1 Deposits 640 more AAVE (enough to cover the DAI debt), disables WETH as collateral",
|
||||
"actions": [
|
||||
{
|
||||
"name": "mint",
|
||||
"args": {
|
||||
"reserve": "LEND",
|
||||
"amount": "64000",
|
||||
"reserve": "AAVE",
|
||||
"amount": "640",
|
||||
"user": "1"
|
||||
},
|
||||
"expected": "success"
|
||||
|
@ -192,9 +192,9 @@
|
|||
{
|
||||
"name": "deposit",
|
||||
"args": {
|
||||
"reserve": "LEND",
|
||||
"reserve": "AAVE",
|
||||
|
||||
"amount": "64000",
|
||||
"amount": "640",
|
||||
"user": "1"
|
||||
},
|
||||
"expected": "success"
|
||||
|
@ -212,12 +212,12 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"description": "User 1 disables LEND as collateral (revert expected)",
|
||||
"description": "User 1 disables AAVE as collateral (revert expected)",
|
||||
"actions": [
|
||||
{
|
||||
"name": "setUseAsCollateral",
|
||||
"args": {
|
||||
"reserve": "LEND",
|
||||
"reserve": "AAVE",
|
||||
|
||||
"user": "1",
|
||||
"useAsCollateral": "false"
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
} from '../../../helpers/contracts-getters';
|
||||
import {tEthereumAddress} from '../../../helpers/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {getDb, BRE} from '../../../helpers/misc-utils';
|
||||
import {getDb, DRE} from '../../../helpers/misc-utils';
|
||||
import {AaveProtocolTestHelpers} from '../../../types/AaveProtocolTestHelpers';
|
||||
|
||||
export const getReserveData = async (
|
||||
|
@ -104,7 +104,7 @@ export const getUserData = async (
|
|||
|
||||
export const getReserveAddressFromSymbol = async (symbol: string) => {
|
||||
const token = await getMintableErc20(
|
||||
(await getDb().get(`${symbol}.${BRE.network.name}`).value()).address
|
||||
(await getDb().get(`${symbol}.${DRE.network.name}`).value()).address
|
||||
);
|
||||
|
||||
if (!token) {
|
||||
|
|
|
@ -21,7 +21,7 @@ makeSuite('LendingPoolAddressesProvider', (testEnv: TestEnv) => {
|
|||
addressesProvider.setLendingPoolImpl,
|
||||
addressesProvider.setLendingPoolConfiguratorImpl,
|
||||
addressesProvider.setLendingPoolCollateralManager,
|
||||
addressesProvider.setAaveAdmin,
|
||||
addressesProvider.setPoolAdmin,
|
||||
addressesProvider.setPriceOracle,
|
||||
addressesProvider.setLendingRateOracle,
|
||||
]) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import {BRE} from '../helpers/misc-utils';
|
||||
import {DRE} from '../helpers/misc-utils';
|
||||
import {oneEther} from '../helpers/constants';
|
||||
import {convertToCurrencyDecimals} from '../helpers/contracts-helpers';
|
||||
import {makeSuite} from './helpers/make-suite';
|
||||
|
@ -21,7 +21,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
|
|||
INVALID_HF,
|
||||
LPCM_SPECIFIED_CURRENCY_NOT_BORROWED_BY_USER,
|
||||
LPCM_COLLATERAL_CANNOT_BE_LIQUIDATED,
|
||||
P_IS_PAUSED,
|
||||
LP_IS_PAUSED,
|
||||
} = ProtocolErrors;
|
||||
|
||||
it('LIQUIDATION - Deposits WETH, borrows DAI/Check liquidation fails because health factor is above 1', async () => {
|
||||
|
@ -96,7 +96,10 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
|
|||
|
||||
const userGlobalData = await pool.getUserAccountData(borrower.address);
|
||||
|
||||
expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt(oneEther, INVALID_HF);
|
||||
expect(userGlobalData.healthFactor.toString()).to.be.bignumber.lt(
|
||||
oneEther.toString(),
|
||||
INVALID_HF
|
||||
);
|
||||
});
|
||||
|
||||
it('LIQUIDATION - Tries to liquidate a different currency than the loan principal', async () => {
|
||||
|
@ -182,7 +185,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) =>
|
|||
}
|
||||
|
||||
const txTimestamp = new BigNumber(
|
||||
(await BRE.ethers.provider.getBlock(tx.blockNumber)).timestamp
|
||||
(await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp
|
||||
);
|
||||
|
||||
const variableDebtBeforeTx = calcExpectedVariableDebtTokenBalance(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import {BRE, increaseTime} from '../helpers/misc-utils';
|
||||
import {DRE, increaseTime} from '../helpers/misc-utils';
|
||||
import {oneEther} from '../helpers/constants';
|
||||
import {convertToCurrencyDecimals} from '../helpers/contracts-helpers';
|
||||
import {makeSuite} from './helpers/make-suite';
|
||||
|
@ -185,7 +185,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
|
|||
return;
|
||||
}
|
||||
const txTimestamp = new BigNumber(
|
||||
(await BRE.ethers.provider.getBlock(tx.blockNumber)).timestamp
|
||||
(await DRE.ethers.provider.getBlock(tx.blockNumber)).timestamp
|
||||
);
|
||||
|
||||
const stableDebtBeforeTx = calcExpectedStableDebtTokenBalance(
|
||||
|
@ -302,7 +302,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
|
|||
const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address);
|
||||
const ethReserveDataBefore = await helpersContract.getReserveData(weth.address);
|
||||
|
||||
const amountToLiquidate = BRE.ethers.BigNumber.from(
|
||||
const amountToLiquidate = DRE.ethers.BigNumber.from(
|
||||
userReserveDataBefore.currentStableDebt.toString()
|
||||
)
|
||||
.div(2)
|
||||
|
@ -380,25 +380,25 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
|
|||
);
|
||||
});
|
||||
|
||||
it('User 4 deposits 1000 LEND - drops HF, liquidates the LEND, which results on a lower amount being liquidated', async () => {
|
||||
const {lend, usdc, users, pool, oracle, helpersContract} = testEnv;
|
||||
it('User 4 deposits 10 AAVE - drops HF, liquidates the AAVE, which results on a lower amount being liquidated', async () => {
|
||||
const {aave, usdc, users, pool, oracle, helpersContract} = testEnv;
|
||||
|
||||
const depositor = users[3];
|
||||
const borrower = users[4];
|
||||
const liquidator = users[5];
|
||||
|
||||
//mints LEND to borrower
|
||||
await lend.connect(borrower.signer).mint(await convertToCurrencyDecimals(lend.address, '1000'));
|
||||
//mints AAVE to borrower
|
||||
await aave.connect(borrower.signer).mint(await convertToCurrencyDecimals(aave.address, '10'));
|
||||
|
||||
//approve protocol to access the borrower wallet
|
||||
await lend.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL);
|
||||
await aave.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL);
|
||||
|
||||
//borrower deposits 1000 LEND
|
||||
const amountLENDtoDeposit = await convertToCurrencyDecimals(lend.address, '1000');
|
||||
//borrower deposits 10 AAVE
|
||||
const amountToDeposit = await convertToCurrencyDecimals(aave.address, '10');
|
||||
|
||||
await pool
|
||||
.connect(borrower.signer)
|
||||
.deposit(lend.address, amountLENDtoDeposit, borrower.address, '0');
|
||||
.deposit(aave.address, amountToDeposit, borrower.address, '0');
|
||||
const usdcPrice = await oracle.getAssetPrice(usdc.address);
|
||||
|
||||
//drops HF below 1
|
||||
|
@ -421,19 +421,19 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
|
|||
);
|
||||
|
||||
const usdcReserveDataBefore = await helpersContract.getReserveData(usdc.address);
|
||||
const lendReserveDataBefore = await helpersContract.getReserveData(lend.address);
|
||||
const aaveReserveDataBefore = await helpersContract.getReserveData(aave.address);
|
||||
|
||||
const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString())
|
||||
.div(2)
|
||||
.decimalPlaces(0, BigNumber.ROUND_DOWN)
|
||||
.toFixed(0);
|
||||
|
||||
const collateralPrice = await oracle.getAssetPrice(lend.address);
|
||||
const collateralPrice = await oracle.getAssetPrice(aave.address);
|
||||
const principalPrice = await oracle.getAssetPrice(usdc.address);
|
||||
|
||||
await pool
|
||||
.connect(liquidator.signer)
|
||||
.liquidationCall(lend.address, usdc.address, borrower.address, amountToLiquidate, false);
|
||||
.liquidationCall(aave.address, usdc.address, borrower.address, amountToLiquidate, false);
|
||||
|
||||
const userReserveDataAfter = await helpersContract.getUserReserveData(
|
||||
usdc.address,
|
||||
|
@ -443,17 +443,17 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
|
|||
const userGlobalDataAfter = await pool.getUserAccountData(borrower.address);
|
||||
|
||||
const usdcReserveDataAfter = await helpersContract.getReserveData(usdc.address);
|
||||
const lendReserveDataAfter = await helpersContract.getReserveData(lend.address);
|
||||
const aaveReserveDataAfter = await helpersContract.getReserveData(aave.address);
|
||||
|
||||
const lendConfiguration = await helpersContract.getReserveConfigurationData(lend.address);
|
||||
const collateralDecimals = lendConfiguration.decimals.toString();
|
||||
const liquidationBonus = lendConfiguration.liquidationBonus.toString();
|
||||
const aaveConfiguration = await helpersContract.getReserveConfigurationData(aave.address);
|
||||
const collateralDecimals = aaveConfiguration.decimals.toString();
|
||||
const liquidationBonus = aaveConfiguration.liquidationBonus.toString();
|
||||
|
||||
const principalDecimals = (
|
||||
await helpersContract.getReserveConfigurationData(usdc.address)
|
||||
).decimals.toString();
|
||||
|
||||
const expectedCollateralLiquidated = oneEther.multipliedBy('1000');
|
||||
const expectedCollateralLiquidated = oneEther.multipliedBy('10');
|
||||
|
||||
const expectedPrincipal = new BigNumber(collateralPrice.toString())
|
||||
.times(expectedCollateralLiquidated)
|
||||
|
@ -484,8 +484,8 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset',
|
|||
'Invalid principal available liquidity'
|
||||
);
|
||||
|
||||
expect(lendReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual(
|
||||
new BigNumber(lendReserveDataBefore.availableLiquidity.toString())
|
||||
expect(aaveReserveDataAfter.availableLiquidity.toString()).to.be.bignumber.almostEqual(
|
||||
new BigNumber(aaveReserveDataBefore.availableLiquidity.toString())
|
||||
.minus(expectedCollateralLiquidated)
|
||||
.toFixed(0),
|
||||
'Invalid collateral available liquidity'
|
||||
|
|
|
@ -13,7 +13,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver;
|
||||
|
||||
const {
|
||||
P_IS_PAUSED,
|
||||
LP_IS_PAUSED,
|
||||
INVALID_FROM_BALANCE_AFTER_TRANSFER,
|
||||
INVALID_TO_BALANCE_AFTER_TRANSFER,
|
||||
} = ProtocolErrors;
|
||||
|
@ -39,12 +39,12 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
const user1Balance = await aDai.balanceOf(users[1].address);
|
||||
|
||||
// Configurator pauses the pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
// User 0 tries the transfer to User 1
|
||||
await expect(
|
||||
aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit)
|
||||
).to.revertedWith(P_IS_PAUSED);
|
||||
).to.revertedWith(LP_IS_PAUSED);
|
||||
|
||||
const pausedFromBalance = await aDai.balanceOf(users[0].address);
|
||||
const pausedToBalance = await aDai.balanceOf(users[1].address);
|
||||
|
@ -59,7 +59,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
);
|
||||
|
||||
// Configurator unpauses the pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
|
||||
// User 0 succeeds transfer to User 1
|
||||
await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit);
|
||||
|
@ -88,13 +88,13 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL);
|
||||
|
||||
// Configurator pauses the pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
await expect(
|
||||
pool.connect(users[0].signer).deposit(dai.address, amountDAItoDeposit, users[0].address, '0')
|
||||
).to.revertedWith(P_IS_PAUSED);
|
||||
).to.revertedWith(LP_IS_PAUSED);
|
||||
|
||||
// Configurator unpauses the pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
|
||||
it('Withdraw', async () => {
|
||||
|
@ -111,32 +111,15 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
.deposit(dai.address, amountDAItoDeposit, users[0].address, '0');
|
||||
|
||||
// Configurator pauses the pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
// user tries to burn
|
||||
await expect(
|
||||
pool.connect(users[0].signer).withdraw(dai.address, amountDAItoDeposit, users[0].address)
|
||||
).to.revertedWith(P_IS_PAUSED);
|
||||
).to.revertedWith(LP_IS_PAUSED);
|
||||
|
||||
// Configurator unpauses the pool
|
||||
await configurator.setPoolPause(false);
|
||||
});
|
||||
|
||||
it('DelegateBorrowAllowance', async () => {
|
||||
const {pool, dai, users, configurator} = testEnv;
|
||||
|
||||
const user = users[1];
|
||||
const toUser = users[2];
|
||||
// Pause the pool
|
||||
await configurator.setPoolPause(true);
|
||||
|
||||
// Try to execute liquidation
|
||||
await expect(
|
||||
pool.connect(user.signer).delegateBorrowAllowance([dai.address], toUser.address, ['1'], ['1'])
|
||||
).revertedWith(P_IS_PAUSED);
|
||||
|
||||
// Unpause the pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
|
||||
it('Borrow', async () => {
|
||||
|
@ -144,15 +127,15 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
|
||||
const user = users[1];
|
||||
// Pause the pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
// Try to execute liquidation
|
||||
await expect(
|
||||
pool.connect(user.signer).borrow(dai.address, '1', '1', '0', user.address)
|
||||
).revertedWith(P_IS_PAUSED);
|
||||
).revertedWith(LP_IS_PAUSED);
|
||||
|
||||
// Unpause the pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
|
||||
it('Repay', async () => {
|
||||
|
@ -160,15 +143,15 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
|
||||
const user = users[1];
|
||||
// Pause the pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
// Try to execute liquidation
|
||||
await expect(pool.connect(user.signer).repay(dai.address, '1', '1', user.address)).revertedWith(
|
||||
P_IS_PAUSED
|
||||
LP_IS_PAUSED
|
||||
);
|
||||
|
||||
// Unpause the pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
|
||||
it('Flash loan', async () => {
|
||||
|
@ -181,7 +164,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||
|
||||
// Pause pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
await expect(
|
||||
pool
|
||||
|
@ -195,10 +178,10 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
'0x10',
|
||||
'0'
|
||||
)
|
||||
).revertedWith(P_IS_PAUSED);
|
||||
).revertedWith(LP_IS_PAUSED);
|
||||
|
||||
// Unpause pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
|
||||
it('Liquidation call', async () => {
|
||||
|
@ -271,15 +254,15 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
.toFixed(0);
|
||||
|
||||
// Pause pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
// Do liquidation
|
||||
expect(
|
||||
await expect(
|
||||
pool.liquidationCall(weth.address, usdc.address, borrower.address, amountToLiquidate, true)
|
||||
).revertedWith(P_IS_PAUSED);
|
||||
).revertedWith(LP_IS_PAUSED);
|
||||
|
||||
// Unpause pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
|
||||
it('SwapBorrowRateMode', async () => {
|
||||
|
@ -300,29 +283,29 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address);
|
||||
|
||||
// Pause pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
// Try to repay
|
||||
await expect(
|
||||
pool.connect(user.signer).swapBorrowRateMode(usdc.address, RateMode.Stable)
|
||||
).revertedWith(P_IS_PAUSED);
|
||||
).revertedWith(LP_IS_PAUSED);
|
||||
|
||||
// Unpause pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
|
||||
it('RebalanceStableBorrowRate', async () => {
|
||||
const {pool, dai, users, configurator} = testEnv;
|
||||
const user = users[1];
|
||||
// Pause pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
await expect(
|
||||
pool.connect(user.signer).rebalanceStableBorrowRate(dai.address, user.address)
|
||||
).revertedWith(P_IS_PAUSED);
|
||||
).revertedWith(LP_IS_PAUSED);
|
||||
|
||||
// Unpause pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
|
||||
it('setUserUseReserveAsCollateral', async () => {
|
||||
|
@ -335,13 +318,13 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
|||
await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0');
|
||||
|
||||
// Pause pool
|
||||
await configurator.setPoolPause(true);
|
||||
await configurator.connect(users[1].signer).setPoolPause(true);
|
||||
|
||||
await expect(
|
||||
pool.connect(user.signer).setUserUseReserveAsCollateral(weth.address, false)
|
||||
).revertedWith(P_IS_PAUSED);
|
||||
).revertedWith(LP_IS_PAUSED);
|
||||
|
||||
// Unpause pool
|
||||
await configurator.setPoolPause(false);
|
||||
await configurator.connect(users[1].signer).setPoolPause(false);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -16,9 +16,9 @@ makeSuite('Stable debt token tests', (testEnv: TestEnv) => {
|
|||
|
||||
const stableDebtContract = await getStableDebtToken(daiStableDebtTokenAddress);
|
||||
|
||||
await expect(stableDebtContract.mint(deployer.address, '1', '1')).to.be.revertedWith(
|
||||
AT_CALLER_MUST_BE_LENDING_POOL
|
||||
);
|
||||
await expect(
|
||||
stableDebtContract.mint(deployer.address, deployer.address, '1', '1')
|
||||
).to.be.revertedWith(AT_CALLER_MUST_BE_LENDING_POOL);
|
||||
});
|
||||
|
||||
it('Tries to invoke burn not being the LendingPool', async () => {
|
||||
|
|
|
@ -1,277 +0,0 @@
|
|||
// import {
|
||||
// ITestEnv,
|
||||
// ContractsInstancesOrigin,
|
||||
// iBasicDistributionParams,
|
||||
// iTokenBalances,
|
||||
// iDistributionParams,
|
||||
// } from '../utils/types';
|
||||
// import {
|
||||
// TokenDistributorInstance,
|
||||
// MintableERC20Instance,
|
||||
// } from '../utils/typechain-types/truffle-contracts';
|
||||
// import {testEnvProvider} from '../utils/truffle/dlp-tests-env';
|
||||
// import {
|
||||
// TOKEN_DISTRIBUTOR_PERCENTAGE_BASE,
|
||||
// ETHEREUM_ADDRESS,
|
||||
// ONE_ADDRESS,
|
||||
// NIL_ADDRESS,
|
||||
// } from '../utils/constants';
|
||||
// import BigNumber from 'bignumber.js';
|
||||
|
||||
// import {expect} from 'chai';
|
||||
|
||||
// const testAndExecMintAndTransferTokens = async (
|
||||
// tokenInstance: MintableERC20Instance,
|
||||
// amount: string,
|
||||
// minter: string,
|
||||
// receiver: string
|
||||
// ) => {
|
||||
// const initialMinterBalance = new BigNumber(await tokenInstance.balanceOf(minter));
|
||||
// const initialReceiverBalance = new BigNumber(await tokenInstance.balanceOf(receiver));
|
||||
// await tokenInstance.mint(amount, {
|
||||
// from: minter,
|
||||
// });
|
||||
|
||||
// expect(initialMinterBalance.plus(amount).toFixed()).to.be.equal(
|
||||
// new BigNumber(await tokenInstance.balanceOf(minter)).toFixed()
|
||||
// );
|
||||
|
||||
// await tokenInstance.transfer(receiver, amount, {from: minter});
|
||||
|
||||
// expect(initialReceiverBalance.plus(amount).toFixed()).to.be.equal(
|
||||
// new BigNumber(await tokenInstance.balanceOf(receiver)).toFixed()
|
||||
// );
|
||||
// };
|
||||
|
||||
// const testAndExecEthTransfer = async (
|
||||
// amount: string,
|
||||
// sender: string,
|
||||
// receiver: string,
|
||||
// web3: Web3
|
||||
// ) => {
|
||||
// const initialReceiverEthBalance = await web3.eth.getBalance(receiver);
|
||||
// await web3.eth.sendTransaction({
|
||||
// from: sender,
|
||||
// to: receiver,
|
||||
// value: amount,
|
||||
// });
|
||||
|
||||
// expect(new BigNumber(initialReceiverEthBalance).plus(amount).toFixed()).to.be.equal(
|
||||
// await web3.eth.getBalance(receiver)
|
||||
// );
|
||||
// };
|
||||
|
||||
// const testAndExecDistributeToken = async (
|
||||
// tokenInstances: MintableERC20Instance[],
|
||||
// tokenToBurnInstance: MintableERC20Instance,
|
||||
// tokenDistributorInstance: TokenDistributorInstance,
|
||||
// distributionParams: iBasicDistributionParams[]
|
||||
// ) => {
|
||||
// const tokenBalancesBefore: iTokenBalances[] = [];
|
||||
// for (const [index, tokenInstance] of tokenInstances.entries()) {
|
||||
// const {receivers} = distributionParams[index];
|
||||
// const tokenBalancesReceiversBefore: string[][] = [[], []];
|
||||
// for (const receiver of receivers) {
|
||||
// if (receiver.toUpperCase() !== NIL_ADDRESS.toUpperCase()) {
|
||||
// tokenBalancesReceiversBefore[index].push(
|
||||
// (await tokenInstance.balanceOf(receiver)).toString()
|
||||
// );
|
||||
// } else {
|
||||
// tokenBalancesReceiversBefore[index].push(
|
||||
// (await tokenToBurnInstance.balanceOf(
|
||||
// await tokenDistributorInstance.recipientBurn()
|
||||
// )).toString()
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// tokenBalancesBefore.push({
|
||||
// tokenDistributor: (await tokenInstance.balanceOf(
|
||||
// tokenDistributorInstance.address
|
||||
// )).toString(),
|
||||
// receivers: tokenBalancesReceiversBefore[index],
|
||||
// });
|
||||
// }
|
||||
|
||||
// const tokenDistribution = await tokenDistributorInstance.getDistribution();
|
||||
|
||||
// await tokenDistributorInstance.distribute(
|
||||
// tokenInstances.map(tokenInstance => tokenInstance.address)
|
||||
// );
|
||||
|
||||
// const tokenBalanceOfDistributorAfter: string[] = [];
|
||||
// for (const [indexToken, tokenInstance] of tokenInstances.entries()) {
|
||||
// const newLength = tokenBalanceOfDistributorAfter.push(
|
||||
// (await tokenInstance.balanceOf(tokenDistributorInstance.address)).toString()
|
||||
// );
|
||||
// const receivers = distributionParams[indexToken].receivers;
|
||||
// expect(parseInt(tokenBalanceOfDistributorAfter[newLength - 1])).to.be.within(
|
||||
// 0,
|
||||
// receivers.length - 1
|
||||
// );
|
||||
|
||||
// for (const [indexReceiver, receiver] of receivers.entries()) {
|
||||
// const receiverPercentage = new BigNumber(tokenDistribution[1][indexReceiver]).toFixed();
|
||||
// const tokenAmountToReceiver = new BigNumber(tokenBalancesBefore[indexToken].tokenDistributor)
|
||||
// .multipliedBy(receiverPercentage)
|
||||
// .dividedBy(TOKEN_DISTRIBUTOR_PERCENTAGE_BASE)
|
||||
// .toFixed(0, BigNumber.ROUND_DOWN);
|
||||
// const tokenBalanceOfReceiverAfter = (await tokenInstance.balanceOf(receiver)).toString();
|
||||
// const recipientBurnBalanceAfter = (await tokenToBurnInstance.balanceOf(
|
||||
// await tokenDistributorInstance.recipientBurn()
|
||||
// )).toString();
|
||||
// if (receiver.toUpperCase() !== NIL_ADDRESS.toUpperCase()) {
|
||||
// expect(tokenBalanceOfReceiverAfter).to.be.equal(
|
||||
// new BigNumber(tokenBalancesBefore[indexToken].receivers[indexReceiver])
|
||||
// .plus(tokenAmountToReceiver)
|
||||
// .toFixed()
|
||||
// );
|
||||
// } else {
|
||||
// // 1 ether received from "burning" DAI and 264 LEND wei received from the 34% of the 777 LEND amount sent to the token distributor
|
||||
// expect(recipientBurnBalanceAfter).to.be.equal('1000000000000000264');
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// const testAndExecDistributeEth = async (
|
||||
// tokenDistributorInstance: TokenDistributorInstance,
|
||||
// tokenToBurnInstance: MintableERC20Instance,
|
||||
// distributionParams: iBasicDistributionParams,
|
||||
// web3: Web3
|
||||
// ) => {
|
||||
// const {receivers} = distributionParams;
|
||||
|
||||
// const ethBalancesReceiversBefore = [];
|
||||
// for (const receiver of receivers) {
|
||||
// if (receiver.toUpperCase() !== NIL_ADDRESS.toUpperCase()) {
|
||||
// ethBalancesReceiversBefore.push(await web3.eth.getBalance(receiver));
|
||||
// } else {
|
||||
// ethBalancesReceiversBefore.push(await web3.eth.getBalance(ONE_ADDRESS));
|
||||
// }
|
||||
// }
|
||||
// const ethBalancesBefore: iTokenBalances = {
|
||||
// tokenDistributor: await web3.eth.getBalance(tokenDistributorInstance.address),
|
||||
// receivers: ethBalancesReceiversBefore,
|
||||
// };
|
||||
|
||||
// const ethDistribution = await tokenDistributorInstance.getDistribution();
|
||||
|
||||
// await tokenDistributorInstance.distribute([ETHEREUM_ADDRESS]);
|
||||
|
||||
// const ethBalanceOfDistributorAfter = await web3.eth.getBalance(tokenDistributorInstance.address);
|
||||
|
||||
// expect(parseInt(ethBalanceOfDistributorAfter)).to.be.within(0, receivers.length - 1);
|
||||
|
||||
// for (const [index, receiver] of receivers.entries()) {
|
||||
// const receiverPercentage = new BigNumber(ethDistribution[1][index]).toFixed();
|
||||
// const ethAmountToReceiver = new BigNumber(ethBalancesBefore.tokenDistributor)
|
||||
// .multipliedBy(receiverPercentage)
|
||||
// .dividedBy(TOKEN_DISTRIBUTOR_PERCENTAGE_BASE)
|
||||
// .toFixed(0, BigNumber.ROUND_DOWN);
|
||||
// const ethBalanceOfReceiverAfter = await web3.eth.getBalance(receiver);
|
||||
// const recipientBurnBalanceAfter = (await tokenToBurnInstance.balanceOf(
|
||||
// await tokenDistributorInstance.recipientBurn()
|
||||
// )).toString();
|
||||
// if (receiver.toUpperCase() !== NIL_ADDRESS.toUpperCase()) {
|
||||
// expect(ethBalanceOfReceiverAfter).to.be.equal(
|
||||
// new BigNumber(ethBalancesBefore.receivers[index]).plus(ethAmountToReceiver).toFixed()
|
||||
// );
|
||||
// } else {
|
||||
// // 1 ether received from "burning" DAI, 1 ether from ETH and 264 LEND wei received from the 34% of the 777 LEND amount sent to the token distributor
|
||||
// expect(recipientBurnBalanceAfter).to.be.equal('2000000000000000264');
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// contract('TokenDistributor', async ([deployer, ...users]) => {
|
||||
// // let _testEnvProvider: ITestEnv;
|
||||
// // let _tokenDistributorInstance: TokenDistributorInstance;
|
||||
// // let _tokenInstances: iAavePoolAssets<MintableERC20Instance>;
|
||||
// // let _web3: Web3;
|
||||
// // let _depositorAddress: string;
|
||||
// // let _daiDistributionParams: iDistributionParams;
|
||||
// // let _lendDistributionParams: iDistributionParams;
|
||||
// // let _ethDistributionParams: iDistributionParams;
|
||||
|
||||
// // before('Initializing LendingPoolConfigurator test variables', async () => {
|
||||
// // _testEnvProvider = await testEnvProvider(
|
||||
// // artifacts,
|
||||
// // [deployer, ...users],
|
||||
// // ContractsInstancesOrigin.TruffleArtifacts
|
||||
// // );
|
||||
|
||||
// // const {
|
||||
// // deployedInstances: {tokenDistributorInstance},
|
||||
// // getAllAssetsInstances,
|
||||
// // getWeb3,
|
||||
// // getFirstDepositorAddressOnTests,
|
||||
// // getFeeDistributionParams,
|
||||
// // } = _testEnvProvider;
|
||||
// // _tokenDistributorInstance = tokenDistributorInstance;
|
||||
// // _tokenInstances = await getAllAssetsInstances();
|
||||
// // _web3 = await getWeb3();
|
||||
// // _depositorAddress = await getFirstDepositorAddressOnTests();
|
||||
|
||||
// // const {receivers, percentages} = await getFeeDistributionParams();
|
||||
// // _daiDistributionParams = {
|
||||
// // amountToDistribute: '333',
|
||||
// // receivers,
|
||||
// // percentages,
|
||||
// // };
|
||||
// // _lendDistributionParams = {
|
||||
// // amountToDistribute: '777',
|
||||
// // receivers,
|
||||
// // percentages,
|
||||
// // };
|
||||
// // _ethDistributionParams = {
|
||||
// // amountToDistribute: '2534',
|
||||
// // receivers,
|
||||
// // percentages,
|
||||
// // };
|
||||
// // });
|
||||
|
||||
// // it('Transfers ETH to the TokenDistributor', async () => {
|
||||
// // await testAndExecEthTransfer(
|
||||
// // _ethDistributionParams.amountToDistribute,
|
||||
// // deployer,
|
||||
// // _tokenDistributorInstance.address,
|
||||
// // _web3
|
||||
// // );
|
||||
// // });
|
||||
|
||||
// // it('Mints and transfers DAI to the TokenDistributor', async () => {
|
||||
// // await testAndExecMintAndTransferTokens(
|
||||
// // _tokenInstances.DAI,
|
||||
// // _daiDistributionParams.amountToDistribute,
|
||||
// // _depositorAddress,
|
||||
// // _tokenDistributorInstance.address
|
||||
// // );
|
||||
// // });
|
||||
|
||||
// // it('Mints and transfers LEND to the TokenDistributor', async () => {
|
||||
// // await testAndExecMintAndTransferTokens(
|
||||
// // _tokenInstances.LEND,
|
||||
// // _lendDistributionParams.amountToDistribute,
|
||||
// // _depositorAddress,
|
||||
// // _tokenDistributorInstance.address
|
||||
// // );
|
||||
// // });
|
||||
|
||||
// // it('distribute() for the receivers', async () => {
|
||||
// // await testAndExecDistributeToken(
|
||||
// // [_tokenInstances.DAI, _tokenInstances.LEND],
|
||||
// // _tokenInstances.LEND,
|
||||
// // _tokenDistributorInstance,
|
||||
// // [_daiDistributionParams, _lendDistributionParams]
|
||||
// // );
|
||||
// // });
|
||||
|
||||
// // it('Distributes the ETH to the receivers', async () => {
|
||||
// // await testAndExecDistributeEth(
|
||||
// // _tokenDistributorInstance,
|
||||
// // _tokenInstances.LEND,
|
||||
// // _ethDistributionParams,
|
||||
// // _web3
|
||||
// // );
|
||||
// // });
|
||||
// });
|
|
@ -19,7 +19,7 @@ import {
|
|||
} from '../helpers/contracts-deployments';
|
||||
|
||||
makeSuite('Upgradeability', (testEnv: TestEnv) => {
|
||||
const {LPC_CALLER_NOT_AAVE_ADMIN} = ProtocolErrors;
|
||||
const {CALLER_NOT_POOL_ADMIN} = ProtocolErrors;
|
||||
let newATokenAddress: string;
|
||||
let newStableTokenAddress: string;
|
||||
let newVariableTokenAddress: string;
|
||||
|
@ -61,7 +61,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => {
|
|||
|
||||
await expect(
|
||||
configurator.connect(users[1].signer).updateAToken(dai.address, newATokenAddress)
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Upgrades the DAI Atoken implementation ', async () => {
|
||||
|
@ -83,7 +83,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => {
|
|||
configurator
|
||||
.connect(users[1].signer)
|
||||
.updateStableDebtToken(dai.address, newStableTokenAddress)
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Upgrades the DAI stable debt token implementation ', async () => {
|
||||
|
@ -109,7 +109,7 @@ makeSuite('Upgradeability', (testEnv: TestEnv) => {
|
|||
configurator
|
||||
.connect(users[1].signer)
|
||||
.updateVariableDebtToken(dai.address, newVariableTokenAddress)
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_AAVE_ADMIN);
|
||||
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Upgrades the DAI variable debt token implementation ', async () => {
|
||||
|
|
|
@ -15,9 +15,9 @@ makeSuite('Variable debt token tests', (testEnv: TestEnv) => {
|
|||
|
||||
const variableDebtContract = await getVariableDebtToken(daiVariableDebtTokenAddress);
|
||||
|
||||
await expect(variableDebtContract.mint(deployer.address, '1', '1')).to.be.revertedWith(
|
||||
AT_CALLER_MUST_BE_LENDING_POOL
|
||||
);
|
||||
await expect(
|
||||
variableDebtContract.mint(deployer.address, deployer.address, '1', '1')
|
||||
).to.be.revertedWith(AT_CALLER_MUST_BE_LENDING_POOL);
|
||||
});
|
||||
|
||||
it('Tries to invoke burn not being the LendingPool', async () => {
|
||||
|
|
350
test/weth-gateway.spec.ts
Normal file
350
test/weth-gateway.spec.ts
Normal file
|
@ -0,0 +1,350 @@
|
|||
import {MAX_UINT_AMOUNT} from '../helpers/constants';
|
||||
import {convertToCurrencyDecimals} from '../helpers/contracts-helpers';
|
||||
import {makeSuite, TestEnv} from './helpers/make-suite';
|
||||
import {parseEther} from 'ethers/lib/utils';
|
||||
import {DRE, waitForTx} from '../helpers/misc-utils';
|
||||
import {BigNumber} from 'ethers';
|
||||
import {getStableDebtToken, getVariableDebtToken} from '../helpers/contracts-getters';
|
||||
import {deploySelfdestructTransferMock} from '../helpers/contracts-deployments';
|
||||
|
||||
const {expect} = require('chai');
|
||||
|
||||
makeSuite('Use native ETH at LendingPool via WETHGateway', (testEnv: TestEnv) => {
|
||||
const zero = BigNumber.from('0');
|
||||
const depositSize = parseEther('5');
|
||||
|
||||
it('Deposit WETH', async () => {
|
||||
const {users, wethGateway, aWETH, pool} = testEnv;
|
||||
|
||||
const user = users[1];
|
||||
|
||||
// Deposit with native ETH
|
||||
await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize});
|
||||
|
||||
const aTokensBalance = await aWETH.balanceOf(user.address);
|
||||
|
||||
expect(aTokensBalance).to.be.gt(zero);
|
||||
expect(aTokensBalance).to.be.gte(depositSize);
|
||||
});
|
||||
|
||||
it('Withdraw WETH - Partial', async () => {
|
||||
const {users, wethGateway, aWETH, pool} = testEnv;
|
||||
|
||||
const user = users[1];
|
||||
const priorEthersBalance = await user.signer.getBalance();
|
||||
const aTokensBalance = await aWETH.balanceOf(user.address);
|
||||
|
||||
expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.');
|
||||
|
||||
// Partially withdraw native ETH
|
||||
const partialWithdraw = await convertToCurrencyDecimals(aWETH.address, '2');
|
||||
|
||||
// Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether
|
||||
const approveTx = await aWETH
|
||||
.connect(user.signer)
|
||||
.approve(wethGateway.address, MAX_UINT_AMOUNT);
|
||||
const {gasUsed: approveGas} = await waitForTx(approveTx);
|
||||
|
||||
// Partial Withdraw and send native Ether to user
|
||||
const {gasUsed: withdrawGas} = await waitForTx(
|
||||
await wethGateway.connect(user.signer).withdrawETH(partialWithdraw, user.address)
|
||||
);
|
||||
|
||||
const afterPartialEtherBalance = await user.signer.getBalance();
|
||||
const afterPartialATokensBalance = await aWETH.balanceOf(user.address);
|
||||
const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice);
|
||||
|
||||
expect(afterPartialEtherBalance).to.be.equal(
|
||||
priorEthersBalance.add(partialWithdraw).sub(gasCosts),
|
||||
'User ETHER balance should contain the partial withdraw'
|
||||
);
|
||||
expect(afterPartialATokensBalance).to.be.equal(
|
||||
aTokensBalance.sub(partialWithdraw),
|
||||
'User aWETH balance should be substracted'
|
||||
);
|
||||
});
|
||||
|
||||
it('Withdraw WETH - Full', async () => {
|
||||
const {users, aWETH, wethGateway, pool} = testEnv;
|
||||
|
||||
const user = users[1];
|
||||
const priorEthersBalance = await user.signer.getBalance();
|
||||
const aTokensBalance = await aWETH.balanceOf(user.address);
|
||||
|
||||
expect(aTokensBalance).to.be.gt(zero, 'User should have aTokens.');
|
||||
|
||||
// Approve the aTokens to Gateway so Gateway can withdraw and convert to Ether
|
||||
const approveTx = await aWETH
|
||||
.connect(user.signer)
|
||||
.approve(wethGateway.address, MAX_UINT_AMOUNT);
|
||||
const {gasUsed: approveGas} = await waitForTx(approveTx);
|
||||
|
||||
// Full withdraw
|
||||
const {gasUsed: withdrawGas} = await waitForTx(
|
||||
await wethGateway.connect(user.signer).withdrawETH(MAX_UINT_AMOUNT, user.address)
|
||||
);
|
||||
|
||||
const afterFullEtherBalance = await user.signer.getBalance();
|
||||
const afterFullATokensBalance = await aWETH.balanceOf(user.address);
|
||||
const gasCosts = approveGas.add(withdrawGas).mul(approveTx.gasPrice);
|
||||
|
||||
expect(afterFullEtherBalance).to.be.eq(
|
||||
priorEthersBalance.add(aTokensBalance).sub(gasCosts),
|
||||
'User ETHER balance should contain the full withdraw'
|
||||
);
|
||||
expect(afterFullATokensBalance).to.be.eq(0, 'User aWETH balance should be zero');
|
||||
});
|
||||
|
||||
it('Borrow stable WETH and Full Repay with ETH', async () => {
|
||||
const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv;
|
||||
const borrowSize = parseEther('1');
|
||||
const repaySize = borrowSize.add(borrowSize.mul(5).div(100));
|
||||
const user = users[1];
|
||||
|
||||
const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address);
|
||||
|
||||
const stableDebtToken = await getStableDebtToken(stableDebtTokenAddress);
|
||||
|
||||
// Deposit with native ETH
|
||||
await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize});
|
||||
|
||||
const aTokensBalance = await aWETH.balanceOf(user.address);
|
||||
|
||||
expect(aTokensBalance).to.be.gt(zero);
|
||||
expect(aTokensBalance).to.be.gte(depositSize);
|
||||
|
||||
// Borrow WETH with WETH as collateral
|
||||
await waitForTx(
|
||||
await pool.connect(user.signer).borrow(weth.address, borrowSize, '1', '0', user.address)
|
||||
);
|
||||
|
||||
const debtBalance = await stableDebtToken.balanceOf(user.address);
|
||||
|
||||
expect(debtBalance).to.be.gt(zero);
|
||||
|
||||
// Full Repay WETH with native ETH
|
||||
await waitForTx(
|
||||
await wethGateway
|
||||
.connect(user.signer)
|
||||
.repayETH(MAX_UINT_AMOUNT, '1', user.address, {value: repaySize})
|
||||
);
|
||||
|
||||
const debtBalanceAfterRepay = await stableDebtToken.balanceOf(user.address);
|
||||
expect(debtBalanceAfterRepay).to.be.eq(zero);
|
||||
});
|
||||
|
||||
it('Borrow variable WETH and Full Repay with ETH', async () => {
|
||||
const {users, wethGateway, aWETH, weth, pool, helpersContract} = testEnv;
|
||||
const borrowSize = parseEther('1');
|
||||
const repaySize = borrowSize.add(borrowSize.mul(5).div(100));
|
||||
const user = users[1];
|
||||
|
||||
const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(
|
||||
weth.address
|
||||
);
|
||||
|
||||
const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress);
|
||||
|
||||
// Deposit with native ETH
|
||||
await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize});
|
||||
|
||||
const aTokensBalance = await aWETH.balanceOf(user.address);
|
||||
|
||||
expect(aTokensBalance).to.be.gt(zero);
|
||||
expect(aTokensBalance).to.be.gte(depositSize);
|
||||
|
||||
// Borrow WETH with WETH as collateral
|
||||
await waitForTx(
|
||||
await pool.connect(user.signer).borrow(weth.address, borrowSize, '2', '0', user.address)
|
||||
);
|
||||
|
||||
const debtBalance = await varDebtToken.balanceOf(user.address);
|
||||
|
||||
expect(debtBalance).to.be.gt(zero);
|
||||
|
||||
// Partial Repay WETH loan with native ETH
|
||||
const partialPayment = repaySize.div(2);
|
||||
await waitForTx(
|
||||
await wethGateway
|
||||
.connect(user.signer)
|
||||
.repayETH(partialPayment, '2', user.address, {value: partialPayment})
|
||||
);
|
||||
|
||||
const debtBalanceAfterPartialRepay = await varDebtToken.balanceOf(user.address);
|
||||
expect(debtBalanceAfterPartialRepay).to.be.lt(debtBalance);
|
||||
|
||||
// Full Repay WETH loan with native ETH
|
||||
await waitForTx(
|
||||
await wethGateway
|
||||
.connect(user.signer)
|
||||
.repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: repaySize})
|
||||
);
|
||||
const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address);
|
||||
expect(debtBalanceAfterFullRepay).to.be.eq(zero);
|
||||
});
|
||||
|
||||
it('Borrow ETH via delegateApprove ETH and repays back', async () => {
|
||||
const {users, wethGateway, aWETH, weth, helpersContract} = testEnv;
|
||||
const borrowSize = parseEther('1');
|
||||
const user = users[2];
|
||||
const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(
|
||||
weth.address
|
||||
);
|
||||
const varDebtToken = await getVariableDebtToken(variableDebtTokenAddress);
|
||||
|
||||
const priorDebtBalance = await varDebtToken.balanceOf(user.address);
|
||||
expect(priorDebtBalance).to.be.eq(zero);
|
||||
|
||||
// Deposit WETH with native ETH
|
||||
await wethGateway.connect(user.signer).depositETH(user.address, '0', {value: depositSize});
|
||||
|
||||
const aTokensBalance = await aWETH.balanceOf(user.address);
|
||||
|
||||
expect(aTokensBalance).to.be.gt(zero);
|
||||
expect(aTokensBalance).to.be.gte(depositSize);
|
||||
|
||||
// Delegates borrowing power of WETH to WETHGateway
|
||||
await waitForTx(
|
||||
await varDebtToken.connect(user.signer).approveDelegation(wethGateway.address, borrowSize)
|
||||
);
|
||||
|
||||
// Borrows ETH with WETH as collateral
|
||||
await waitForTx(await wethGateway.connect(user.signer).borrowETH(borrowSize, '2', '0'));
|
||||
|
||||
const debtBalance = await varDebtToken.balanceOf(user.address);
|
||||
|
||||
expect(debtBalance).to.be.gt(zero);
|
||||
|
||||
// Full Repay WETH loan with native ETH
|
||||
await waitForTx(
|
||||
await wethGateway
|
||||
.connect(user.signer)
|
||||
.repayETH(MAX_UINT_AMOUNT, '2', user.address, {value: borrowSize.mul(2)})
|
||||
);
|
||||
const debtBalanceAfterFullRepay = await varDebtToken.balanceOf(user.address);
|
||||
expect(debtBalanceAfterFullRepay).to.be.eq(zero);
|
||||
});
|
||||
|
||||
it('Should revert if receiver function receives Ether if not WETH', async () => {
|
||||
const {users, wethGateway} = testEnv;
|
||||
const user = users[0];
|
||||
const amount = parseEther('1');
|
||||
|
||||
// Call receiver function (empty data + value)
|
||||
await expect(
|
||||
user.signer.sendTransaction({
|
||||
to: wethGateway.address,
|
||||
value: amount,
|
||||
gasLimit: DRE.network.config.gas,
|
||||
})
|
||||
).to.be.revertedWith('Receive not allowed');
|
||||
});
|
||||
|
||||
it('Should revert if fallback functions is called with Ether', async () => {
|
||||
const {users, wethGateway} = testEnv;
|
||||
const user = users[0];
|
||||
const amount = parseEther('1');
|
||||
const fakeABI = ['function wantToCallFallback()'];
|
||||
const abiCoder = new DRE.ethers.utils.Interface(fakeABI);
|
||||
const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []);
|
||||
|
||||
// Call fallback function with value
|
||||
await expect(
|
||||
user.signer.sendTransaction({
|
||||
to: wethGateway.address,
|
||||
data: fakeMethodEncoded,
|
||||
value: amount,
|
||||
gasLimit: DRE.network.config.gas,
|
||||
})
|
||||
).to.be.revertedWith('Fallback not allowed');
|
||||
});
|
||||
|
||||
it('Should revert if fallback functions is called', async () => {
|
||||
const {users, wethGateway} = testEnv;
|
||||
const user = users[0];
|
||||
|
||||
const fakeABI = ['function wantToCallFallback()'];
|
||||
const abiCoder = new DRE.ethers.utils.Interface(fakeABI);
|
||||
const fakeMethodEncoded = abiCoder.encodeFunctionData('wantToCallFallback', []);
|
||||
|
||||
// Call fallback function without value
|
||||
await expect(
|
||||
user.signer.sendTransaction({
|
||||
to: wethGateway.address,
|
||||
data: fakeMethodEncoded,
|
||||
gasLimit: DRE.network.config.gas,
|
||||
})
|
||||
).to.be.revertedWith('Fallback not allowed');
|
||||
});
|
||||
|
||||
it('Getters should retrieve correct state', async () => {
|
||||
const {aWETH, weth, pool, wethGateway} = testEnv;
|
||||
|
||||
const WETHAddress = await wethGateway.getWETHAddress();
|
||||
const aWETHAddress = await wethGateway.getAWETHAddress();
|
||||
const poolAddress = await wethGateway.getLendingPoolAddress();
|
||||
|
||||
expect(WETHAddress).to.be.equal(weth.address);
|
||||
expect(aWETHAddress).to.be.equal(aWETH.address);
|
||||
expect(poolAddress).to.be.equal(pool.address);
|
||||
});
|
||||
|
||||
it('Owner can do emergency token recovery', async () => {
|
||||
const {users, dai, wethGateway, deployer} = testEnv;
|
||||
const user = users[0];
|
||||
const amount = parseEther('1');
|
||||
|
||||
await dai.connect(user.signer).mint(amount);
|
||||
const daiBalanceAfterMint = await dai.balanceOf(user.address);
|
||||
|
||||
await dai.connect(user.signer).transfer(wethGateway.address, amount);
|
||||
const daiBalanceAfterBadTransfer = await dai.balanceOf(user.address);
|
||||
expect(daiBalanceAfterBadTransfer).to.be.eq(
|
||||
daiBalanceAfterMint.sub(amount),
|
||||
'User should have lost the funds here.'
|
||||
);
|
||||
|
||||
await wethGateway
|
||||
.connect(deployer.signer)
|
||||
.emergencyTokenTransfer(dai.address, user.address, amount);
|
||||
const daiBalanceAfterRecovery = await dai.balanceOf(user.address);
|
||||
|
||||
expect(daiBalanceAfterRecovery).to.be.eq(
|
||||
daiBalanceAfterMint,
|
||||
'User should recover the funds due emergency token transfer'
|
||||
);
|
||||
});
|
||||
|
||||
it('Owner can do emergency native ETH recovery', async () => {
|
||||
const {users, wethGateway, deployer} = testEnv;
|
||||
const user = users[0];
|
||||
const amount = parseEther('1');
|
||||
const userBalancePriorCall = await user.signer.getBalance();
|
||||
|
||||
// Deploy contract with payable selfdestruct contract
|
||||
const selfdestructContract = await deploySelfdestructTransferMock();
|
||||
|
||||
// Selfdestruct the mock, pointing to WETHGateway address
|
||||
const callTx = await selfdestructContract
|
||||
.connect(user.signer)
|
||||
.destroyAndTransfer(wethGateway.address, {value: amount});
|
||||
const {gasUsed} = await waitForTx(callTx);
|
||||
const gasFees = gasUsed.mul(callTx.gasPrice);
|
||||
const userBalanceAfterCall = await user.signer.getBalance();
|
||||
|
||||
expect(userBalanceAfterCall).to.be.eq(userBalancePriorCall.sub(amount).sub(gasFees), '');
|
||||
'User should have lost the funds';
|
||||
|
||||
// Recover the funds from the contract and sends back to the user
|
||||
await wethGateway.connect(deployer.signer).emergencyEtherTransfer(user.address, amount);
|
||||
|
||||
const userBalanceAfterRecovery = await user.signer.getBalance();
|
||||
const wethGatewayAfterRecovery = await DRE.ethers.provider.getBalance(wethGateway.address);
|
||||
|
||||
expect(userBalanceAfterRecovery).to.be.eq(
|
||||
userBalancePriorCall.sub(gasFees),
|
||||
'User should recover the funds due emergency eth transfer.'
|
||||
);
|
||||
expect(wethGatewayAfterRecovery).to.be.eq('0', 'WETHGateway ether balance should be zero.');
|
||||
});
|
||||
});
|
|
@ -1,16 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2019",
|
||||
"target": "es2019",
|
||||
"module": "commonjs",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"outDir": "dist",
|
||||
"resolveJsonModule": true,
|
||||
"downlevelIteration": true
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["./**/*"],
|
||||
"include": ["./scripts", "./test"],
|
||||
"files": [
|
||||
"./buidler.config.ts",
|
||||
"./hardhat.config.ts",
|
||||
"node_modules/@nomiclabs/buidler-ethers/src/type-extensions.d.ts",
|
||||
"node_modules/buidler-typechain/src/type-extensions.d.ts",
|
||||
"node_modules/@nomiclabs/buidler-waffle/src/type-extensions.d.ts",
|
||||
|
|
Loading…
Reference in New Issue
Block a user