mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
feat: Added Rewards Aware ATokens tests and scripts.
This commit is contained in:
parent
55a9880c79
commit
d6ede6c87e
|
@ -70,4 +70,5 @@ export const MOCK_CHAINLINK_AGGREGATORS_PRICES = {
|
||||||
STAKE: oneEther.multipliedBy('0.003620948469').toFixed(),
|
STAKE: oneEther.multipliedBy('0.003620948469').toFixed(),
|
||||||
xSUSHI: oneEther.multipliedBy('0.00913428586').toFixed(),
|
xSUSHI: oneEther.multipliedBy('0.00913428586').toFixed(),
|
||||||
USD: '5848466240000000',
|
USD: '5848466240000000',
|
||||||
|
REW: oneEther.multipliedBy('0.00137893825230').toFixed(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Contract } from 'ethers';
|
import { Contract } from 'ethers';
|
||||||
import { DRE } from './misc-utils';
|
import { DRE, notFalsyOrZeroAddress } from './misc-utils';
|
||||||
import {
|
import {
|
||||||
tEthereumAddress,
|
tEthereumAddress,
|
||||||
eContractid,
|
eContractid,
|
||||||
|
@ -10,12 +10,12 @@ import {
|
||||||
IReserveParams,
|
IReserveParams,
|
||||||
PoolConfiguration,
|
PoolConfiguration,
|
||||||
eEthereumNetwork,
|
eEthereumNetwork,
|
||||||
|
eNetwork,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { MintableERC20 } from '../types/MintableERC20';
|
import { MintableERC20 } from '../types/MintableERC20';
|
||||||
import { MockContract } from 'ethereum-waffle';
|
import { MockContract } from 'ethereum-waffle';
|
||||||
import { getReservesConfigByPool } from './configuration';
|
import { ConfigNames, getReservesConfigByPool, loadPoolConfig } from './configuration';
|
||||||
import { getFirstSigner } from './contracts-getters';
|
import { getFirstSigner } from './contracts-getters';
|
||||||
import { ZERO_ADDRESS } from './constants';
|
|
||||||
import {
|
import {
|
||||||
AaveProtocolDataProviderFactory,
|
AaveProtocolDataProviderFactory,
|
||||||
ATokenFactory,
|
ATokenFactory,
|
||||||
|
@ -49,6 +49,8 @@ import {
|
||||||
WETH9MockedFactory,
|
WETH9MockedFactory,
|
||||||
WETHGatewayFactory,
|
WETHGatewayFactory,
|
||||||
FlashLiquidationAdapterFactory,
|
FlashLiquidationAdapterFactory,
|
||||||
|
RewardsTokenFactory,
|
||||||
|
RewardsATokenMockFactory,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {
|
import {
|
||||||
withSaveAndVerify,
|
withSaveAndVerify,
|
||||||
|
@ -57,6 +59,8 @@ import {
|
||||||
insertContractAddressInDb,
|
insertContractAddressInDb,
|
||||||
deployContract,
|
deployContract,
|
||||||
verifyContract,
|
verifyContract,
|
||||||
|
getParamPerNetwork,
|
||||||
|
getOptionalParamAddressPerNetwork,
|
||||||
} from './contracts-helpers';
|
} from './contracts-helpers';
|
||||||
import { StableAndVariableTokensHelperFactory } from '../types/StableAndVariableTokensHelperFactory';
|
import { StableAndVariableTokensHelperFactory } from '../types/StableAndVariableTokensHelperFactory';
|
||||||
import { MintableDelegationERC20 } from '../types/MintableDelegationERC20';
|
import { MintableDelegationERC20 } from '../types/MintableDelegationERC20';
|
||||||
|
@ -347,20 +351,20 @@ export const deployVariableDebtToken = async (
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deployGenericStableDebtToken = async () =>
|
export const deployGenericStableDebtToken = async (verify?: boolean) =>
|
||||||
withSaveAndVerify(
|
withSaveAndVerify(
|
||||||
await new StableDebtTokenFactory(await getFirstSigner()).deploy(),
|
await new StableDebtTokenFactory(await getFirstSigner()).deploy(),
|
||||||
eContractid.StableDebtToken,
|
eContractid.StableDebtToken,
|
||||||
[],
|
[],
|
||||||
false
|
verify
|
||||||
);
|
);
|
||||||
|
|
||||||
export const deployGenericVariableDebtToken = async () =>
|
export const deployGenericVariableDebtToken = async (verify?: boolean) =>
|
||||||
withSaveAndVerify(
|
withSaveAndVerify(
|
||||||
await new VariableDebtTokenFactory(await getFirstSigner()).deploy(),
|
await new VariableDebtTokenFactory(await getFirstSigner()).deploy(),
|
||||||
eContractid.VariableDebtToken,
|
eContractid.VariableDebtToken,
|
||||||
[],
|
[],
|
||||||
false
|
verify
|
||||||
);
|
);
|
||||||
|
|
||||||
export const deployGenericAToken = async (
|
export const deployGenericAToken = async (
|
||||||
|
@ -395,7 +399,7 @@ export const deployGenericAToken = async (
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deployGenericATokenImpl = async (verify: boolean) =>
|
export const deployGenericATokenImpl = async (verify?: boolean) =>
|
||||||
withSaveAndVerify(
|
withSaveAndVerify(
|
||||||
await new ATokenFactory(await getFirstSigner()).deploy(),
|
await new ATokenFactory(await getFirstSigner()).deploy(),
|
||||||
eContractid.AToken,
|
eContractid.AToken,
|
||||||
|
@ -435,7 +439,7 @@ export const deployDelegationAwareAToken = async (
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const deployDelegationAwareATokenImpl = async (verify: boolean) =>
|
export const deployDelegationAwareATokenImpl = async (verify?: boolean) =>
|
||||||
withSaveAndVerify(
|
withSaveAndVerify(
|
||||||
await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(),
|
await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(),
|
||||||
eContractid.DelegationAwareAToken,
|
eContractid.DelegationAwareAToken,
|
||||||
|
@ -473,8 +477,7 @@ export const deployMockTokens = async (config: PoolConfiguration, verify?: boole
|
||||||
[
|
[
|
||||||
tokenSymbol,
|
tokenSymbol,
|
||||||
tokenSymbol,
|
tokenSymbol,
|
||||||
configData[tokenSymbol as keyof iMultiPoolsAssets<IReserveParams>].reserveDecimals ||
|
configData[tokenSymbol]?.reserveDecimals || defaultDecimals.toString(),
|
||||||
defaultDecimals.toString(),
|
|
||||||
],
|
],
|
||||||
verify
|
verify
|
||||||
);
|
);
|
||||||
|
@ -633,3 +636,81 @@ export const deployFlashLiquidationAdapter = async (
|
||||||
args,
|
args,
|
||||||
verify
|
verify
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const deployRewardsMockedToken = async (verify?: boolean) =>
|
||||||
|
withSaveAndVerify(
|
||||||
|
await new RewardsTokenFactory(await getFirstSigner()).deploy(),
|
||||||
|
eContractid.RewardsToken,
|
||||||
|
[],
|
||||||
|
verify
|
||||||
|
);
|
||||||
|
|
||||||
|
export const deployRewardATokenMock = async (verify?: boolean) => {
|
||||||
|
return withSaveAndVerify(
|
||||||
|
await new RewardsATokenMockFactory(await getFirstSigner()).deploy(),
|
||||||
|
eContractid.RewardsATokenMock,
|
||||||
|
[],
|
||||||
|
verify
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const chooseATokenDeployment = (id: eContractid) => {
|
||||||
|
switch (id) {
|
||||||
|
case eContractid.AToken:
|
||||||
|
return deployGenericATokenImpl;
|
||||||
|
case eContractid.DelegationAwareAToken:
|
||||||
|
return deployDelegationAwareATokenImpl;
|
||||||
|
case eContractid.RewardsATokenMock:
|
||||||
|
return deployRewardATokenMock;
|
||||||
|
default:
|
||||||
|
throw Error(`Missing aToken implementation deployment script for: ${id}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deployATokenImplementations = async (
|
||||||
|
pool: ConfigNames,
|
||||||
|
reservesConfig: { [key: string]: IReserveParams },
|
||||||
|
verify?: boolean
|
||||||
|
) => {
|
||||||
|
const poolConfig = loadPoolConfig(pool);
|
||||||
|
const network = <eNetwork>DRE.network.name;
|
||||||
|
|
||||||
|
// Obtain the different AToken implementations of all reserves inside the Market config
|
||||||
|
const aTokenImplementations = [
|
||||||
|
...Object.entries(reservesConfig).reduce<Set<eContractid>>((acc, [, entry]) => {
|
||||||
|
acc.add(entry.aTokenImpl);
|
||||||
|
return acc;
|
||||||
|
}, new Set<eContractid>()),
|
||||||
|
];
|
||||||
|
|
||||||
|
console.log(aTokenImplementations);
|
||||||
|
|
||||||
|
for (let x = 0; x < aTokenImplementations.length; x++) {
|
||||||
|
const aTokenAddress = getOptionalParamAddressPerNetwork(
|
||||||
|
poolConfig[aTokenImplementations[x].toString()],
|
||||||
|
network
|
||||||
|
);
|
||||||
|
if (!notFalsyOrZeroAddress(aTokenAddress)) {
|
||||||
|
const deployImplementationMethod = chooseATokenDeployment(aTokenImplementations[x]);
|
||||||
|
console.log(`Deploying implementation`, aTokenImplementations[x]);
|
||||||
|
await deployImplementationMethod(verify);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debt tokens, for now all Market configs follows same implementations
|
||||||
|
const genericStableDebtTokenAddress = getOptionalParamAddressPerNetwork(
|
||||||
|
poolConfig.StableDebtTokenImplementation,
|
||||||
|
network
|
||||||
|
);
|
||||||
|
const geneticVariableDebtTokenAddress = getOptionalParamAddressPerNetwork(
|
||||||
|
poolConfig.VariableDebtTokenImplementation,
|
||||||
|
network
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!notFalsyOrZeroAddress(genericStableDebtTokenAddress)) {
|
||||||
|
await deployGenericStableDebtToken(verify);
|
||||||
|
}
|
||||||
|
if (!notFalsyOrZeroAddress(geneticVariableDebtTokenAddress)) {
|
||||||
|
await deployGenericVariableDebtToken(verify);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -30,6 +30,8 @@ import {
|
||||||
WETH9MockedFactory,
|
WETH9MockedFactory,
|
||||||
WETHGatewayFactory,
|
WETHGatewayFactory,
|
||||||
FlashLiquidationAdapterFactory,
|
FlashLiquidationAdapterFactory,
|
||||||
|
RewardsATokenMockFactory,
|
||||||
|
RewardsTokenFactory,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { IERC20DetailedFactory } from '../types/IERC20DetailedFactory';
|
import { IERC20DetailedFactory } from '../types/IERC20DetailedFactory';
|
||||||
import { MockTokenMap } from './contracts-helpers';
|
import { MockTokenMap } from './contracts-helpers';
|
||||||
|
@ -364,3 +366,20 @@ export const getFlashLiquidationAdapter = async (address?: tEthereumAddress) =>
|
||||||
.address,
|
.address,
|
||||||
await getFirstSigner()
|
await getFirstSigner()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const getRewardsToken = async (address?: tEthereumAddress) =>
|
||||||
|
await RewardsTokenFactory.connect(
|
||||||
|
address ||
|
||||||
|
(await getDb().get(`${eContractid.RewardsToken}.${DRE.network.name}`).value()).address,
|
||||||
|
await getFirstSigner()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getRewardsATokenMock = async (address?: tEthereumAddress) =>
|
||||||
|
await RewardsATokenMockFactory.connect(
|
||||||
|
address ||
|
||||||
|
(await getDb().get(`${eContractid.RewardsATokenMock}.${DRE.network.name}`).value()).address,
|
||||||
|
await getFirstSigner()
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getRewardsAToken = async (address: tEthereumAddress) =>
|
||||||
|
await RewardsATokenMockFactory.connect(address, await getFirstSigner());
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Contract, Signer, utils, ethers, BigNumberish } from 'ethers';
|
||||||
import { signTypedData_v4 } from 'eth-sig-util';
|
import { signTypedData_v4 } from 'eth-sig-util';
|
||||||
import { fromRpcSig, ECDSASignature } from 'ethereumjs-util';
|
import { fromRpcSig, ECDSASignature } from 'ethereumjs-util';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { getDb, DRE, waitForTx } from './misc-utils';
|
import { getDb, DRE, waitForTx, notFalsyOrZeroAddress } from './misc-utils';
|
||||||
import {
|
import {
|
||||||
tEthereumAddress,
|
tEthereumAddress,
|
||||||
eContractid,
|
eContractid,
|
||||||
|
@ -23,9 +23,12 @@ import { MintableERC20 } from '../types/MintableERC20';
|
||||||
import { Artifact } from 'hardhat/types';
|
import { Artifact } from 'hardhat/types';
|
||||||
import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types';
|
import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types';
|
||||||
import { verifyEtherscanContract } from './etherscan-verification';
|
import { verifyEtherscanContract } from './etherscan-verification';
|
||||||
import { getIErc20Detailed } from './contracts-getters';
|
import { getFirstSigner, getIErc20Detailed } from './contracts-getters';
|
||||||
import { usingTenderly, verifyAtTenderly } from './tenderly-utils';
|
import { usingTenderly, verifyAtTenderly } from './tenderly-utils';
|
||||||
import { usingPolygon, verifyAtPolygon } from './polygon-utils';
|
import { usingPolygon, verifyAtPolygon } from './polygon-utils';
|
||||||
|
import { ConfigNames, loadPoolConfig } from './configuration';
|
||||||
|
import { ZERO_ADDRESS } from './constants';
|
||||||
|
import { RewardsTokenFactory, RewardsATokenMockFactory } from '../types';
|
||||||
|
|
||||||
export type MockTokenMap = { [symbol: string]: MintableERC20 };
|
export type MockTokenMap = { [symbol: string]: MintableERC20 };
|
||||||
|
|
||||||
|
@ -173,6 +176,16 @@ export const getParamPerNetwork = <T>(param: iParamsPerNetwork<T>, network: eNet
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getOptionalParamAddressPerNetwork = (
|
||||||
|
param: iParamsPerNetwork<tEthereumAddress> | undefined | null,
|
||||||
|
network: eNetwork
|
||||||
|
) => {
|
||||||
|
if (!param) {
|
||||||
|
return ZERO_ADDRESS;
|
||||||
|
}
|
||||||
|
return getParamPerNetwork(param, network);
|
||||||
|
};
|
||||||
|
|
||||||
export const getParamPerPool = <T>({ proto, amm, matic }: iParamsPerPool<T>, pool: AavePools) => {
|
export const getParamPerPool = <T>({ proto, amm, matic }: iParamsPerPool<T>, pool: AavePools) => {
|
||||||
switch (pool) {
|
switch (pool) {
|
||||||
case AavePools.proto:
|
case AavePools.proto:
|
||||||
|
@ -335,3 +348,23 @@ export const verifyContract = async (
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getContractAddressWithJsonFallback = async (
|
||||||
|
id: string,
|
||||||
|
pool: ConfigNames
|
||||||
|
): Promise<tEthereumAddress> => {
|
||||||
|
const poolConfig = loadPoolConfig(pool);
|
||||||
|
const network = <eNetwork>DRE.network.name;
|
||||||
|
const db = getDb();
|
||||||
|
|
||||||
|
const contractAtMarketConfig = getOptionalParamAddressPerNetwork(poolConfig[id], network);
|
||||||
|
if (notFalsyOrZeroAddress(contractAtMarketConfig)) {
|
||||||
|
return contractAtMarketConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contractAtDb = await getDb().get(`${id}.${DRE.network.name}`).value();
|
||||||
|
if (contractAtDb?.address) {
|
||||||
|
return contractAtDb.address as tEthereumAddress;
|
||||||
|
}
|
||||||
|
throw Error(`Missing contract address ${id} at Market config and JSON local db`);
|
||||||
|
};
|
||||||
|
|
|
@ -1,48 +1,25 @@
|
||||||
import {
|
import {
|
||||||
eContractid,
|
eContractid,
|
||||||
eEthereumNetwork,
|
|
||||||
eNetwork,
|
eNetwork,
|
||||||
iMultiPoolsAssets,
|
iMultiPoolsAssets,
|
||||||
IReserveParams,
|
IReserveParams,
|
||||||
tEthereumAddress,
|
tEthereumAddress,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { AaveProtocolDataProvider } from '../types/AaveProtocolDataProvider';
|
import { AaveProtocolDataProvider } from '../types/AaveProtocolDataProvider';
|
||||||
import { chunk, DRE, getDb, waitForTx } from './misc-utils';
|
import { chunk, getDb, waitForTx } from './misc-utils';
|
||||||
import {
|
import {
|
||||||
getAaveProtocolDataProvider,
|
|
||||||
getAToken,
|
getAToken,
|
||||||
getATokensAndRatesHelper,
|
getATokensAndRatesHelper,
|
||||||
getLendingPoolAddressesProvider,
|
getLendingPoolAddressesProvider,
|
||||||
getLendingPoolConfiguratorProxy,
|
getLendingPoolConfiguratorProxy,
|
||||||
getStableAndVariableTokensHelper,
|
|
||||||
} from './contracts-getters';
|
} from './contracts-getters';
|
||||||
import { rawInsertContractAddressInDb } from './contracts-helpers';
|
|
||||||
import { BigNumber, BigNumberish, Signer } from 'ethers';
|
|
||||||
import {
|
import {
|
||||||
deployDefaultReserveInterestRateStrategy,
|
getContractAddressWithJsonFallback,
|
||||||
deployDelegationAwareAToken,
|
rawInsertContractAddressInDb,
|
||||||
deployDelegationAwareATokenImpl,
|
} from './contracts-helpers';
|
||||||
deployGenericAToken,
|
import { BigNumber, BigNumberish, Signer } from 'ethers';
|
||||||
deployGenericATokenImpl,
|
import { deployDefaultReserveInterestRateStrategy } from './contracts-deployments';
|
||||||
deployGenericStableDebtToken,
|
import { ConfigNames } from './configuration';
|
||||||
deployGenericVariableDebtToken,
|
|
||||||
deployStableDebtToken,
|
|
||||||
deployVariableDebtToken,
|
|
||||||
} from './contracts-deployments';
|
|
||||||
import { ZERO_ADDRESS } from './constants';
|
|
||||||
import { isZeroAddress } from 'ethereumjs-util';
|
|
||||||
import { DefaultReserveInterestRateStrategy, DelegationAwareAToken } from '../types';
|
|
||||||
|
|
||||||
export const chooseATokenDeployment = (id: eContractid) => {
|
|
||||||
switch (id) {
|
|
||||||
case eContractid.AToken:
|
|
||||||
return deployGenericAToken;
|
|
||||||
case eContractid.DelegationAwareAToken:
|
|
||||||
return deployDelegationAwareAToken;
|
|
||||||
default:
|
|
||||||
throw Error(`Missing aToken deployment script for: ${id}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const initReservesByHelper = async (
|
export const initReservesByHelper = async (
|
||||||
reservesParams: iMultiPoolsAssets<IReserveParams>,
|
reservesParams: iMultiPoolsAssets<IReserveParams>,
|
||||||
|
@ -54,19 +31,16 @@ export const initReservesByHelper = async (
|
||||||
admin: tEthereumAddress,
|
admin: tEthereumAddress,
|
||||||
treasuryAddress: tEthereumAddress,
|
treasuryAddress: tEthereumAddress,
|
||||||
incentivesController: tEthereumAddress,
|
incentivesController: tEthereumAddress,
|
||||||
|
poolName: ConfigNames,
|
||||||
verify: boolean
|
verify: boolean
|
||||||
): Promise<BigNumber> => {
|
): Promise<BigNumber> => {
|
||||||
let gasUsage = BigNumber.from('0');
|
let gasUsage = BigNumber.from('0');
|
||||||
const stableAndVariableDeployer = await getStableAndVariableTokensHelper();
|
|
||||||
|
|
||||||
const addressProvider = await getLendingPoolAddressesProvider();
|
const addressProvider = await getLendingPoolAddressesProvider();
|
||||||
|
|
||||||
// CHUNK CONFIGURATION
|
// CHUNK CONFIGURATION
|
||||||
const initChunks = 4;
|
const initChunks = 4;
|
||||||
|
|
||||||
// Initialize variables for future reserves initialization
|
// Initialize variables for future reserves initialization
|
||||||
let reserveTokens: string[] = [];
|
|
||||||
let reserveInitDecimals: string[] = [];
|
|
||||||
let reserveSymbols: string[] = [];
|
let reserveSymbols: string[] = [];
|
||||||
|
|
||||||
let initInputParams: {
|
let initInputParams: {
|
||||||
|
@ -99,49 +73,8 @@ export const initReservesByHelper = async (
|
||||||
];
|
];
|
||||||
let rateStrategies: Record<string, typeof strategyRates> = {};
|
let rateStrategies: Record<string, typeof strategyRates> = {};
|
||||||
let strategyAddresses: Record<string, tEthereumAddress> = {};
|
let strategyAddresses: Record<string, tEthereumAddress> = {};
|
||||||
let strategyAddressPerAsset: Record<string, string> = {};
|
|
||||||
let aTokenType: Record<string, string> = {};
|
|
||||||
let delegationAwareATokenImplementationAddress = '';
|
|
||||||
let aTokenImplementationAddress = '';
|
|
||||||
let stableDebtTokenImplementationAddress = '';
|
|
||||||
let variableDebtTokenImplementationAddress = '';
|
|
||||||
|
|
||||||
// NOT WORKING ON MATIC, DEPLOYING INDIVIDUAL IMPLs INSTEAD
|
const reserves = Object.entries(reservesParams);
|
||||||
// const tx1 = await waitForTx(
|
|
||||||
// await stableAndVariableDeployer.initDeployment([ZERO_ADDRESS], ["1"])
|
|
||||||
// );
|
|
||||||
// console.log(tx1.events);
|
|
||||||
// tx1.events?.forEach((event, index) => {
|
|
||||||
// stableDebtTokenImplementationAddress = event?.args?.stableToken;
|
|
||||||
// variableDebtTokenImplementationAddress = event?.args?.variableToken;
|
|
||||||
// rawInsertContractAddressInDb(`stableDebtTokenImpl`, stableDebtTokenImplementationAddress);
|
|
||||||
// rawInsertContractAddressInDb(`variableDebtTokenImpl`, variableDebtTokenImplementationAddress);
|
|
||||||
// });
|
|
||||||
//gasUsage = gasUsage.add(tx1.gasUsed);
|
|
||||||
stableDebtTokenImplementationAddress = await (await deployGenericStableDebtToken()).address;
|
|
||||||
variableDebtTokenImplementationAddress = await (await deployGenericVariableDebtToken()).address;
|
|
||||||
|
|
||||||
const aTokenImplementation = await deployGenericATokenImpl(verify);
|
|
||||||
aTokenImplementationAddress = aTokenImplementation.address;
|
|
||||||
rawInsertContractAddressInDb(`aTokenImpl`, aTokenImplementationAddress);
|
|
||||||
|
|
||||||
const delegatedAwareReserves = Object.entries(reservesParams).filter(
|
|
||||||
([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken
|
|
||||||
) as [string, IReserveParams][];
|
|
||||||
|
|
||||||
if (delegatedAwareReserves.length > 0) {
|
|
||||||
const delegationAwareATokenImplementation = await deployDelegationAwareATokenImpl(verify);
|
|
||||||
delegationAwareATokenImplementationAddress = delegationAwareATokenImplementation.address;
|
|
||||||
rawInsertContractAddressInDb(
|
|
||||||
`delegationAwareATokenImpl`,
|
|
||||||
delegationAwareATokenImplementationAddress
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const reserves = Object.entries(reservesParams).filter(
|
|
||||||
([_, { aTokenImpl }]) =>
|
|
||||||
aTokenImpl === eContractid.DelegationAwareAToken || aTokenImpl === eContractid.AToken
|
|
||||||
) as [string, IReserveParams][];
|
|
||||||
|
|
||||||
for (let [symbol, params] of reserves) {
|
for (let [symbol, params] of reserves) {
|
||||||
const { strategy, aTokenImpl, reserveDecimals } = params;
|
const { strategy, aTokenImpl, reserveDecimals } = params;
|
||||||
|
@ -171,44 +104,30 @@ export const initReservesByHelper = async (
|
||||||
// and once under the actual `strategyASSET` key.
|
// and once under the actual `strategyASSET` key.
|
||||||
rawInsertContractAddressInDb(strategy.name, strategyAddresses[strategy.name]);
|
rawInsertContractAddressInDb(strategy.name, strategyAddresses[strategy.name]);
|
||||||
}
|
}
|
||||||
strategyAddressPerAsset[symbol] = strategyAddresses[strategy.name];
|
// Prepare input parameters
|
||||||
console.log('Strategy address for asset %s: %s', symbol, strategyAddressPerAsset[symbol]);
|
|
||||||
|
|
||||||
if (aTokenImpl === eContractid.AToken) {
|
|
||||||
aTokenType[symbol] = 'generic';
|
|
||||||
} else if (aTokenImpl === eContractid.DelegationAwareAToken) {
|
|
||||||
aTokenType[symbol] = 'delegation aware';
|
|
||||||
}
|
|
||||||
|
|
||||||
reserveInitDecimals.push(reserveDecimals);
|
|
||||||
reserveTokens.push(tokenAddresses[symbol]);
|
|
||||||
reserveSymbols.push(symbol);
|
reserveSymbols.push(symbol);
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < reserveSymbols.length; i++) {
|
|
||||||
let aTokenToUse: string;
|
|
||||||
if (aTokenType[reserveSymbols[i]] === 'generic') {
|
|
||||||
aTokenToUse = aTokenImplementationAddress;
|
|
||||||
} else {
|
|
||||||
aTokenToUse = delegationAwareATokenImplementationAddress;
|
|
||||||
}
|
|
||||||
|
|
||||||
initInputParams.push({
|
initInputParams.push({
|
||||||
aTokenImpl: aTokenToUse,
|
aTokenImpl: await getContractAddressWithJsonFallback(aTokenImpl, poolName),
|
||||||
stableDebtTokenImpl: stableDebtTokenImplementationAddress,
|
stableDebtTokenImpl: await getContractAddressWithJsonFallback(
|
||||||
variableDebtTokenImpl: variableDebtTokenImplementationAddress,
|
eContractid.StableDebtToken,
|
||||||
underlyingAssetDecimals: reserveInitDecimals[i],
|
poolName
|
||||||
interestRateStrategyAddress: strategyAddressPerAsset[reserveSymbols[i]],
|
),
|
||||||
underlyingAsset: reserveTokens[i],
|
variableDebtTokenImpl: await getContractAddressWithJsonFallback(
|
||||||
|
eContractid.VariableDebtToken,
|
||||||
|
poolName
|
||||||
|
),
|
||||||
|
underlyingAssetDecimals: reserveDecimals,
|
||||||
|
interestRateStrategyAddress: strategyAddresses[strategy.name],
|
||||||
|
underlyingAsset: tokenAddresses[symbol],
|
||||||
treasury: treasuryAddress,
|
treasury: treasuryAddress,
|
||||||
incentivesController,
|
incentivesController: incentivesController,
|
||||||
underlyingAssetName: reserveSymbols[i],
|
underlyingAssetName: symbol,
|
||||||
aTokenName: `${aTokenNamePrefix} ${reserveSymbols[i]}`,
|
aTokenName: `${aTokenNamePrefix} ${symbol}`,
|
||||||
aTokenSymbol: `a${symbolPrefix}${reserveSymbols[i]}`,
|
aTokenSymbol: `a${symbolPrefix}${symbol}`,
|
||||||
variableDebtTokenName: `${variableDebtTokenNamePrefix} ${symbolPrefix}${reserveSymbols[i]}`,
|
variableDebtTokenName: `${variableDebtTokenNamePrefix} ${symbolPrefix}${symbol}`,
|
||||||
variableDebtTokenSymbol: `variableDebt${symbolPrefix}${reserveSymbols[i]}`,
|
variableDebtTokenSymbol: `variableDebt${symbolPrefix}${symbol}`,
|
||||||
stableDebtTokenName: `${stableDebtTokenNamePrefix} ${reserveSymbols[i]}`,
|
stableDebtTokenName: `${stableDebtTokenNamePrefix} ${symbol}`,
|
||||||
stableDebtTokenSymbol: `stableDebt${symbolPrefix}${reserveSymbols[i]}`,
|
stableDebtTokenSymbol: `stableDebt${symbolPrefix}${symbol}`,
|
||||||
params: '0x10',
|
params: '0x10',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -218,7 +137,6 @@ export const initReservesByHelper = async (
|
||||||
const chunkedInitInputParams = chunk(initInputParams, initChunks);
|
const chunkedInitInputParams = chunk(initInputParams, initChunks);
|
||||||
|
|
||||||
const configurator = await getLendingPoolConfiguratorProxy();
|
const configurator = await getLendingPoolConfiguratorProxy();
|
||||||
//await waitForTx(await addressProvider.setPoolAdmin(admin));
|
|
||||||
|
|
||||||
console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`);
|
console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`);
|
||||||
for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) {
|
for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) {
|
||||||
|
@ -228,10 +146,9 @@ export const initReservesByHelper = async (
|
||||||
|
|
||||||
console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`);
|
console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`);
|
||||||
console.log(' * gasUsed', tx3.gasUsed.toString());
|
console.log(' * gasUsed', tx3.gasUsed.toString());
|
||||||
//gasUsage = gasUsage.add(tx3.gasUsed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return gasUsage; // Deprecated
|
return gasUsage;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getPairsTokenAggregator = (
|
export const getPairsTokenAggregator = (
|
||||||
|
|
|
@ -87,6 +87,8 @@ export enum eContractid {
|
||||||
UniswapLiquiditySwapAdapter = 'UniswapLiquiditySwapAdapter',
|
UniswapLiquiditySwapAdapter = 'UniswapLiquiditySwapAdapter',
|
||||||
UniswapRepayAdapter = 'UniswapRepayAdapter',
|
UniswapRepayAdapter = 'UniswapRepayAdapter',
|
||||||
FlashLiquidationAdapter = 'FlashLiquidationAdapter',
|
FlashLiquidationAdapter = 'FlashLiquidationAdapter',
|
||||||
|
RewardsATokenMock = 'RewardsATokenMock',
|
||||||
|
RewardsToken = 'RewardsToken',
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -237,8 +239,9 @@ export interface iAssetBase<T> {
|
||||||
BptWBTCWETH: T;
|
BptWBTCWETH: T;
|
||||||
BptBALWETH: T;
|
BptBALWETH: T;
|
||||||
WMATIC: T;
|
WMATIC: T;
|
||||||
STAKE: T;
|
|
||||||
xSUSHI: T;
|
xSUSHI: T;
|
||||||
|
STAKE: T;
|
||||||
|
REW: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type iAssetsWithoutETH<T> = Omit<iAssetBase<T>, 'ETH'>;
|
export type iAssetsWithoutETH<T> = Omit<iAssetBase<T>, 'ETH'>;
|
||||||
|
@ -352,6 +355,7 @@ export enum TokenContractId {
|
||||||
WMATIC = 'WMATIC',
|
WMATIC = 'WMATIC',
|
||||||
STAKE = 'STAKE',
|
STAKE = 'STAKE',
|
||||||
xSUSHI = 'xSUSHI',
|
xSUSHI = 'xSUSHI',
|
||||||
|
REW = 'REW',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams {
|
export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams {
|
||||||
|
@ -494,6 +498,8 @@ export interface ICommonConfiguration {
|
||||||
WethGateway: iParamsPerNetwork<tEthereumAddress>;
|
WethGateway: iParamsPerNetwork<tEthereumAddress>;
|
||||||
ReserveFactorTreasuryAddress: iParamsPerNetwork<tEthereumAddress>;
|
ReserveFactorTreasuryAddress: iParamsPerNetwork<tEthereumAddress>;
|
||||||
IncentivesController: iParamsPerNetwork<tEthereumAddress>;
|
IncentivesController: iParamsPerNetwork<tEthereumAddress>;
|
||||||
|
StableDebtTokenImplementation?: iParamsPerNetwork<tEthereumAddress>;
|
||||||
|
VariableDebtTokenImplementation?: iParamsPerNetwork<tEthereumAddress>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IAaveConfiguration extends ICommonConfiguration {
|
export interface IAaveConfiguration extends ICommonConfiguration {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { eContractid, IReserveParams } from '../../helpers/types';
|
import { eContractid, IReserveParams } from '../../helpers/types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
rateStrategyStableOne,
|
rateStrategyStableOne,
|
||||||
rateStrategyStableTwo,
|
rateStrategyStableTwo,
|
||||||
rateStrategyStableThree,
|
rateStrategyStableThree,
|
||||||
|
@ -21,7 +21,7 @@ export const strategyBUSD: IReserveParams = {
|
||||||
stableBorrowRateEnabled: false,
|
stableBorrowRateEnabled: false,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '1000'
|
reserveFactor: '1000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyDAI: IReserveParams = {
|
export const strategyDAI: IReserveParams = {
|
||||||
|
@ -33,7 +33,7 @@ export const strategyDAI: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '1000'
|
reserveFactor: '1000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategySUSD: IReserveParams = {
|
export const strategySUSD: IReserveParams = {
|
||||||
|
@ -45,7 +45,7 @@ export const strategySUSD: IReserveParams = {
|
||||||
stableBorrowRateEnabled: false,
|
stableBorrowRateEnabled: false,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyTUSD: IReserveParams = {
|
export const strategyTUSD: IReserveParams = {
|
||||||
|
@ -57,7 +57,7 @@ export const strategyTUSD: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '1000'
|
reserveFactor: '1000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyUSDC: IReserveParams = {
|
export const strategyUSDC: IReserveParams = {
|
||||||
|
@ -69,7 +69,7 @@ export const strategyUSDC: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '6',
|
reserveDecimals: '6',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '1000'
|
reserveFactor: '1000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyUSDT: IReserveParams = {
|
export const strategyUSDT: IReserveParams = {
|
||||||
|
@ -81,7 +81,7 @@ export const strategyUSDT: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '6',
|
reserveDecimals: '6',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '1000'
|
reserveFactor: '1000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyAAVE: IReserveParams = {
|
export const strategyAAVE: IReserveParams = {
|
||||||
|
@ -93,7 +93,7 @@ export const strategyAAVE: IReserveParams = {
|
||||||
stableBorrowRateEnabled: false,
|
stableBorrowRateEnabled: false,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '0'
|
reserveFactor: '0',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyBAT: IReserveParams = {
|
export const strategyBAT: IReserveParams = {
|
||||||
|
@ -105,7 +105,7 @@ export const strategyBAT: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyENJ: IReserveParams = {
|
export const strategyENJ: IReserveParams = {
|
||||||
|
@ -117,7 +117,7 @@ export const strategyENJ: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyWETH: IReserveParams = {
|
export const strategyWETH: IReserveParams = {
|
||||||
|
@ -129,7 +129,7 @@ export const strategyWETH: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '1000'
|
reserveFactor: '1000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyKNC: IReserveParams = {
|
export const strategyKNC: IReserveParams = {
|
||||||
|
@ -141,7 +141,7 @@ export const strategyKNC: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyLINK: IReserveParams = {
|
export const strategyLINK: IReserveParams = {
|
||||||
|
@ -153,7 +153,7 @@ export const strategyLINK: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyMANA: IReserveParams = {
|
export const strategyMANA: IReserveParams = {
|
||||||
|
@ -165,7 +165,7 @@ export const strategyMANA: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '3500'
|
reserveFactor: '3500',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyMKR: IReserveParams = {
|
export const strategyMKR: IReserveParams = {
|
||||||
|
@ -177,7 +177,7 @@ export const strategyMKR: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyREN: IReserveParams = {
|
export const strategyREN: IReserveParams = {
|
||||||
|
@ -189,7 +189,7 @@ export const strategyREN: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategySNX: IReserveParams = {
|
export const strategySNX: IReserveParams = {
|
||||||
|
@ -201,7 +201,7 @@ export const strategySNX: IReserveParams = {
|
||||||
stableBorrowRateEnabled: false,
|
stableBorrowRateEnabled: false,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '3500'
|
reserveFactor: '3500',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Invalid borrow rates in params currently, replaced with snx params
|
// Invalid borrow rates in params currently, replaced with snx params
|
||||||
|
@ -214,7 +214,7 @@ export const strategyUNI: IReserveParams = {
|
||||||
stableBorrowRateEnabled: false,
|
stableBorrowRateEnabled: false,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.DelegationAwareAToken,
|
aTokenImpl: eContractid.DelegationAwareAToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyWBTC: IReserveParams = {
|
export const strategyWBTC: IReserveParams = {
|
||||||
|
@ -226,7 +226,7 @@ export const strategyWBTC: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '8',
|
reserveDecimals: '8',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyYFI: IReserveParams = {
|
export const strategyYFI: IReserveParams = {
|
||||||
|
@ -238,7 +238,7 @@ export const strategyYFI: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyZRX: IReserveParams = {
|
export const strategyZRX: IReserveParams = {
|
||||||
|
@ -250,7 +250,7 @@ export const strategyZRX: IReserveParams = {
|
||||||
stableBorrowRateEnabled: true,
|
stableBorrowRateEnabled: true,
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '2000'
|
reserveFactor: '2000',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const strategyXSUSHI: IReserveParams = {
|
export const strategyXSUSHI: IReserveParams = {
|
||||||
|
@ -263,4 +263,9 @@ export const strategyXSUSHI: IReserveParams = {
|
||||||
reserveDecimals: '18',
|
reserveDecimals: '18',
|
||||||
aTokenImpl: eContractid.AToken,
|
aTokenImpl: eContractid.AToken,
|
||||||
reserveFactor: '3500',
|
reserveFactor: '3500',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const strategyMockedRewardAwareToken: IReserveParams = {
|
||||||
|
...strategyBAT,
|
||||||
|
aTokenImpl: eContractid.RewardsATokenMock,
|
||||||
|
};
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { task } from 'hardhat/config';
|
import { task } from 'hardhat/config';
|
||||||
import {
|
import {
|
||||||
|
deployATokenImplementations,
|
||||||
deployATokensAndRatesHelper,
|
deployATokensAndRatesHelper,
|
||||||
deployLendingPool,
|
deployLendingPool,
|
||||||
deployLendingPoolConfigurator,
|
deployLendingPoolConfigurator,
|
||||||
|
@ -13,13 +14,15 @@ import {
|
||||||
getLendingPoolConfiguratorProxy,
|
getLendingPoolConfiguratorProxy,
|
||||||
} from '../../helpers/contracts-getters';
|
} from '../../helpers/contracts-getters';
|
||||||
import { insertContractAddressInDb } from '../../helpers/contracts-helpers';
|
import { insertContractAddressInDb } from '../../helpers/contracts-helpers';
|
||||||
|
import { ConfigNames, loadPoolConfig } from '../../helpers/configuration';
|
||||||
|
|
||||||
task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
||||||
.addFlag('verify', 'Verify contracts at Etherscan')
|
.addFlag('verify', 'Verify contracts at Etherscan')
|
||||||
.setAction(async ({ verify }, localBRE) => {
|
.addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`)
|
||||||
|
.setAction(async ({ verify, pool }, localBRE) => {
|
||||||
await localBRE.run('set-DRE');
|
await localBRE.run('set-DRE');
|
||||||
|
|
||||||
const addressesProvider = await getLendingPoolAddressesProvider();
|
const addressesProvider = await getLendingPoolAddressesProvider();
|
||||||
|
const poolConfig = loadPoolConfig(pool);
|
||||||
|
|
||||||
const lendingPoolImpl = await deployLendingPool(verify);
|
const lendingPoolImpl = await deployLendingPool(verify);
|
||||||
|
|
||||||
|
@ -55,4 +58,5 @@ task('dev:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
||||||
[lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address],
|
[lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address],
|
||||||
verify
|
verify
|
||||||
);
|
);
|
||||||
|
await deployATokenImplementations(pool, poolConfig.ReservesConfig, verify);
|
||||||
});
|
});
|
||||||
|
|
|
@ -41,6 +41,7 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.')
|
||||||
VariableDebtTokenNamePrefix,
|
VariableDebtTokenNamePrefix,
|
||||||
SymbolPrefix,
|
SymbolPrefix,
|
||||||
WethGateway,
|
WethGateway,
|
||||||
|
ReservesConfig,
|
||||||
} = poolConfig;
|
} = poolConfig;
|
||||||
const mockTokens = await getAllMockedTokens();
|
const mockTokens = await getAllMockedTokens();
|
||||||
const allTokenAddresses = getAllTokenAddresses(mockTokens);
|
const allTokenAddresses = getAllTokenAddresses(mockTokens);
|
||||||
|
@ -53,14 +54,12 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.')
|
||||||
|
|
||||||
const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address, verify);
|
const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address, verify);
|
||||||
|
|
||||||
const reservesParams = getReservesConfigByPool(AavePools.proto);
|
|
||||||
|
|
||||||
const admin = await addressesProvider.getPoolAdmin();
|
const admin = await addressesProvider.getPoolAdmin();
|
||||||
|
|
||||||
const treasuryAddress = await getTreasuryAddress(poolConfig);
|
const treasuryAddress = await getTreasuryAddress(poolConfig);
|
||||||
|
|
||||||
await initReservesByHelper(
|
await initReservesByHelper(
|
||||||
reservesParams,
|
ReservesConfig,
|
||||||
protoPoolReservesAddresses,
|
protoPoolReservesAddresses,
|
||||||
ATokenNamePrefix,
|
ATokenNamePrefix,
|
||||||
StableDebtTokenNamePrefix,
|
StableDebtTokenNamePrefix,
|
||||||
|
@ -69,9 +68,10 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.')
|
||||||
admin,
|
admin,
|
||||||
treasuryAddress,
|
treasuryAddress,
|
||||||
ZERO_ADDRESS,
|
ZERO_ADDRESS,
|
||||||
|
pool,
|
||||||
verify
|
verify
|
||||||
);
|
);
|
||||||
await configureReservesByHelper(reservesParams, protoPoolReservesAddresses, testHelpers, admin);
|
await configureReservesByHelper(ReservesConfig, protoPoolReservesAddresses, testHelpers, admin);
|
||||||
|
|
||||||
const collateralManager = await deployLendingPoolCollateralManager(verify);
|
const collateralManager = await deployLendingPoolCollateralManager(verify);
|
||||||
await waitForTx(
|
await waitForTx(
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { task } from 'hardhat/config';
|
import { task } from 'hardhat/config';
|
||||||
import { getParamPerNetwork, insertContractAddressInDb } from '../../helpers/contracts-helpers';
|
import { getParamPerNetwork, insertContractAddressInDb } from '../../helpers/contracts-helpers';
|
||||||
import {
|
import {
|
||||||
|
deployATokenImplementations,
|
||||||
deployATokensAndRatesHelper,
|
deployATokensAndRatesHelper,
|
||||||
deployLendingPool,
|
deployLendingPool,
|
||||||
deployLendingPoolConfigurator,
|
deployLendingPoolConfigurator,
|
||||||
|
@ -78,6 +79,7 @@ task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment')
|
||||||
[lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address],
|
[lendingPoolProxy.address, addressesProvider.address, lendingPoolConfiguratorProxy.address],
|
||||||
verify
|
verify
|
||||||
);
|
);
|
||||||
|
await deployATokenImplementations(pool, poolConfig.ReservesConfig, verify);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (DRE.network.name.includes('tenderly')) {
|
if (DRE.network.name.includes('tenderly')) {
|
||||||
const transactionLink = `https://dashboard.tenderly.co/${DRE.config.tenderly.username}/${
|
const transactionLink = `https://dashboard.tenderly.co/${DRE.config.tenderly.username}/${
|
||||||
|
|
|
@ -66,6 +66,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.')
|
||||||
admin,
|
admin,
|
||||||
treasuryAddress,
|
treasuryAddress,
|
||||||
incentivesController,
|
incentivesController,
|
||||||
|
pool,
|
||||||
verify
|
verify
|
||||||
);
|
);
|
||||||
await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin);
|
await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin);
|
||||||
|
|
|
@ -3,9 +3,9 @@ import { eEthereumNetwork } from '../../helpers/types';
|
||||||
import { getTreasuryAddress } from '../../helpers/configuration';
|
import { getTreasuryAddress } from '../../helpers/configuration';
|
||||||
import * as marketConfigs from '../../markets/aave';
|
import * as marketConfigs from '../../markets/aave';
|
||||||
import * as reserveConfigs from '../../markets/aave/reservesConfigs';
|
import * as reserveConfigs from '../../markets/aave/reservesConfigs';
|
||||||
import { chooseATokenDeployment } from '../../helpers/init-helpers';
|
|
||||||
import { getLendingPoolAddressesProvider } from './../../helpers/contracts-getters';
|
import { getLendingPoolAddressesProvider } from './../../helpers/contracts-getters';
|
||||||
import {
|
import {
|
||||||
|
chooseATokenDeployment,
|
||||||
deployDefaultReserveInterestRateStrategy,
|
deployDefaultReserveInterestRateStrategy,
|
||||||
deployStableDebtToken,
|
deployStableDebtToken,
|
||||||
deployVariableDebtToken,
|
deployVariableDebtToken,
|
||||||
|
@ -48,17 +48,7 @@ WRONG RESERVE ASSET SETUP:
|
||||||
);
|
);
|
||||||
const poolAddress = await addressProvider.getLendingPool();
|
const poolAddress = await addressProvider.getLendingPool();
|
||||||
const treasuryAddress = await getTreasuryAddress(marketConfigs.AaveConfig);
|
const treasuryAddress = await getTreasuryAddress(marketConfigs.AaveConfig);
|
||||||
const aToken = await deployCustomAToken(
|
const aToken = await deployCustomAToken(verify);
|
||||||
[
|
|
||||||
poolAddress,
|
|
||||||
reserveAssetAddress,
|
|
||||||
treasuryAddress,
|
|
||||||
ZERO_ADDRESS, // Incentives Controller
|
|
||||||
`Aave interest bearing ${symbol}`,
|
|
||||||
`a${symbol}`,
|
|
||||||
],
|
|
||||||
verify
|
|
||||||
);
|
|
||||||
const stableDebt = await deployStableDebtToken(
|
const stableDebt = await deployStableDebtToken(
|
||||||
[
|
[
|
||||||
poolAddress,
|
poolAddress,
|
||||||
|
|
|
@ -24,7 +24,7 @@ task('aave:dev', 'Deploy development enviroment')
|
||||||
await localBRE.run('dev:deploy-address-provider', { verify });
|
await localBRE.run('dev:deploy-address-provider', { verify });
|
||||||
|
|
||||||
console.log('3. Deploy lending pool');
|
console.log('3. Deploy lending pool');
|
||||||
await localBRE.run('dev:deploy-lending-pool', { verify });
|
await localBRE.run('dev:deploy-lending-pool', { verify, pool: POOL_NAME });
|
||||||
|
|
||||||
console.log('4. Deploy oracles');
|
console.log('4. Deploy oracles');
|
||||||
await localBRE.run('dev:deploy-oracles', { verify, pool: POOL_NAME });
|
await localBRE.run('dev:deploy-oracles', { verify, pool: POOL_NAME });
|
||||||
|
|
|
@ -27,8 +27,9 @@ import {
|
||||||
deployUniswapRepayAdapter,
|
deployUniswapRepayAdapter,
|
||||||
deployFlashLiquidationAdapter,
|
deployFlashLiquidationAdapter,
|
||||||
authorizeWETHGateway,
|
authorizeWETHGateway,
|
||||||
|
deployATokenImplementations,
|
||||||
|
deployRewardsMockedToken,
|
||||||
} from '../../helpers/contracts-deployments';
|
} from '../../helpers/contracts-deployments';
|
||||||
import { eEthereumNetwork } from '../../helpers/types';
|
|
||||||
import { Signer } from 'ethers';
|
import { Signer } from 'ethers';
|
||||||
import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types';
|
import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types';
|
||||||
import { MintableERC20 } from '../../types/MintableERC20';
|
import { MintableERC20 } from '../../types/MintableERC20';
|
||||||
|
@ -55,11 +56,12 @@ import {
|
||||||
getPairsTokenAggregator,
|
getPairsTokenAggregator,
|
||||||
} from '../../helpers/contracts-getters';
|
} from '../../helpers/contracts-getters';
|
||||||
import { WETH9Mocked } from '../../types/WETH9Mocked';
|
import { WETH9Mocked } from '../../types/WETH9Mocked';
|
||||||
|
import { strategyMockedRewardAwareToken } from '../../markets/aave/reservesConfigs';
|
||||||
|
import { RewardsToken } from '../../types';
|
||||||
|
|
||||||
const MOCK_USD_PRICE_IN_WEI = AaveConfig.ProtocolGlobalParams.MockUsdPriceInWei;
|
const MOCK_USD_PRICE_IN_WEI = AaveConfig.ProtocolGlobalParams.MockUsdPriceInWei;
|
||||||
const ALL_ASSETS_INITIAL_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices;
|
const ALL_ASSETS_INITIAL_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices;
|
||||||
const USD_ADDRESS = AaveConfig.ProtocolGlobalParams.UsdAddress;
|
const USD_ADDRESS = AaveConfig.ProtocolGlobalParams.UsdAddress;
|
||||||
const MOCK_CHAINLINK_AGGREGATORS_PRICES = AaveConfig.Mocks.AllAssetsInitialPrices;
|
|
||||||
const LENDING_RATE_ORACLE_RATES_COMMON = AaveConfig.LendingRateOracleRatesCommon;
|
const LENDING_RATE_ORACLE_RATES_COMMON = AaveConfig.LendingRateOracleRatesCommon;
|
||||||
|
|
||||||
const deployAllMockTokens = async (deployer: Signer) => {
|
const deployAllMockTokens = async (deployer: Signer) => {
|
||||||
|
@ -95,9 +97,14 @@ const deployAllMockTokens = async (deployer: Signer) => {
|
||||||
const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
console.time('setup');
|
console.time('setup');
|
||||||
const aaveAdmin = await deployer.getAddress();
|
const aaveAdmin = await deployer.getAddress();
|
||||||
|
const config = loadPoolConfig(ConfigNames.Aave);
|
||||||
|
|
||||||
const mockTokens = await deployAllMockTokens(deployer);
|
const mockTokens: {
|
||||||
console.log('Deployed mocks');
|
[symbol: string]: MockContract | MintableERC20 | WETH9Mocked | RewardsToken;
|
||||||
|
} = {
|
||||||
|
...(await deployAllMockTokens(deployer)),
|
||||||
|
REW: await deployRewardsMockedToken(),
|
||||||
|
};
|
||||||
const addressesProvider = await deployLendingPoolAddressesProvider(AaveConfig.MarketId);
|
const addressesProvider = await deployLendingPoolAddressesProvider(AaveConfig.MarketId);
|
||||||
await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin));
|
await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin));
|
||||||
|
|
||||||
|
@ -191,13 +198,13 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
WMATIC: mockTokens.WMATIC.address,
|
WMATIC: mockTokens.WMATIC.address,
|
||||||
USD: USD_ADDRESS,
|
USD: USD_ADDRESS,
|
||||||
STAKE: mockTokens.STAKE.address,
|
STAKE: mockTokens.STAKE.address,
|
||||||
xSUSHI: mockTokens.xSUSHI.address
|
xSUSHI: mockTokens.xSUSHI.address,
|
||||||
|
REW: mockTokens.REW.address,
|
||||||
},
|
},
|
||||||
fallbackOracle
|
fallbackOracle
|
||||||
);
|
);
|
||||||
|
|
||||||
const mockAggregators = await deployAllMockAggregators(MOCK_CHAINLINK_AGGREGATORS_PRICES);
|
const mockAggregators = await deployAllMockAggregators(ALL_ASSETS_INITIAL_PRICES);
|
||||||
console.log('Mock aggs deployed');
|
|
||||||
const allTokenAddresses = Object.entries(mockTokens).reduce(
|
const allTokenAddresses = Object.entries(mockTokens).reduce(
|
||||||
(accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({
|
(accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({
|
||||||
...accum,
|
...accum,
|
||||||
|
@ -232,17 +239,18 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
aaveAdmin
|
aaveAdmin
|
||||||
);
|
);
|
||||||
|
|
||||||
const reservesParams = getReservesConfigByPool(AavePools.proto);
|
// Reserve params from AAVE pool + mocked tokens
|
||||||
|
const reservesParams = {
|
||||||
|
...config.ReservesConfig,
|
||||||
|
REW: strategyMockedRewardAwareToken,
|
||||||
|
};
|
||||||
|
|
||||||
const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address);
|
const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address);
|
||||||
|
|
||||||
await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address);
|
await deployATokenImplementations(ConfigNames.Aave, reservesParams, false);
|
||||||
|
|
||||||
const admin = await deployer.getAddress();
|
const admin = await deployer.getAddress();
|
||||||
|
|
||||||
console.log('Initialize configuration');
|
|
||||||
|
|
||||||
const config = loadPoolConfig(ConfigNames.Aave);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ATokenNamePrefix,
|
ATokenNamePrefix,
|
||||||
StableDebtTokenNamePrefix,
|
StableDebtTokenNamePrefix,
|
||||||
|
@ -261,6 +269,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
admin,
|
admin,
|
||||||
treasuryAddress,
|
treasuryAddress,
|
||||||
ZERO_ADDRESS,
|
ZERO_ADDRESS,
|
||||||
|
ConfigNames.Aave,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ import {
|
||||||
getUniswapLiquiditySwapAdapter,
|
getUniswapLiquiditySwapAdapter,
|
||||||
getUniswapRepayAdapter,
|
getUniswapRepayAdapter,
|
||||||
getFlashLiquidationAdapter,
|
getFlashLiquidationAdapter,
|
||||||
|
getRewardsToken,
|
||||||
|
getRewardsATokenMock,
|
||||||
} from '../../../helpers/contracts-getters';
|
} from '../../../helpers/contracts-getters';
|
||||||
import { eEthereumNetwork, tEthereumAddress } from '../../../helpers/types';
|
import { eEthereumNetwork, tEthereumAddress } from '../../../helpers/types';
|
||||||
import { LendingPool } from '../../../types/LendingPool';
|
import { LendingPool } from '../../../types/LendingPool';
|
||||||
|
@ -37,7 +39,7 @@ import { WETH9Mocked } from '../../../types/WETH9Mocked';
|
||||||
import { WETHGateway } from '../../../types/WETHGateway';
|
import { WETHGateway } from '../../../types/WETHGateway';
|
||||||
import { solidity } from 'ethereum-waffle';
|
import { solidity } from 'ethereum-waffle';
|
||||||
import { AaveConfig } from '../../../markets/aave';
|
import { AaveConfig } from '../../../markets/aave';
|
||||||
import { FlashLiquidationAdapter } from '../../../types';
|
import { FlashLiquidationAdapter, RewardsATokenMock, RewardsToken } from '../../../types';
|
||||||
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
import { HardhatRuntimeEnvironment } from 'hardhat/types';
|
||||||
import { usingTenderly } from '../../../helpers/tenderly-utils';
|
import { usingTenderly } from '../../../helpers/tenderly-utils';
|
||||||
|
|
||||||
|
@ -62,6 +64,8 @@ export interface TestEnv {
|
||||||
aDai: AToken;
|
aDai: AToken;
|
||||||
usdc: MintableERC20;
|
usdc: MintableERC20;
|
||||||
aave: MintableERC20;
|
aave: MintableERC20;
|
||||||
|
rew: RewardsToken;
|
||||||
|
aRew: RewardsATokenMock;
|
||||||
addressesProvider: LendingPoolAddressesProvider;
|
addressesProvider: LendingPoolAddressesProvider;
|
||||||
uniswapLiquiditySwapAdapter: UniswapLiquiditySwapAdapter;
|
uniswapLiquiditySwapAdapter: UniswapLiquiditySwapAdapter;
|
||||||
uniswapRepayAdapter: UniswapRepayAdapter;
|
uniswapRepayAdapter: UniswapRepayAdapter;
|
||||||
|
@ -88,6 +92,8 @@ const testEnv: TestEnv = {
|
||||||
aDai: {} as AToken,
|
aDai: {} as AToken,
|
||||||
usdc: {} as MintableERC20,
|
usdc: {} as MintableERC20,
|
||||||
aave: {} as MintableERC20,
|
aave: {} as MintableERC20,
|
||||||
|
rew: {} as RewardsToken,
|
||||||
|
aRew: {} as RewardsATokenMock,
|
||||||
addressesProvider: {} as LendingPoolAddressesProvider,
|
addressesProvider: {} as LendingPoolAddressesProvider,
|
||||||
uniswapLiquiditySwapAdapter: {} as UniswapLiquiditySwapAdapter,
|
uniswapLiquiditySwapAdapter: {} as UniswapLiquiditySwapAdapter,
|
||||||
uniswapRepayAdapter: {} as UniswapRepayAdapter,
|
uniswapRepayAdapter: {} as UniswapRepayAdapter,
|
||||||
|
@ -129,7 +135,7 @@ export async function initializeMakeSuite() {
|
||||||
|
|
||||||
const allTokens = await testEnv.helpersContract.getAllATokens();
|
const allTokens = await testEnv.helpersContract.getAllATokens();
|
||||||
const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aDAI')?.tokenAddress;
|
const aDaiAddress = allTokens.find((aToken) => aToken.symbol === 'aDAI')?.tokenAddress;
|
||||||
|
const aRewAddress = allTokens.find((aToken) => aToken.symbol === 'aREW')?.tokenAddress;
|
||||||
const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aWETH')?.tokenAddress;
|
const aWEthAddress = allTokens.find((aToken) => aToken.symbol === 'aWETH')?.tokenAddress;
|
||||||
|
|
||||||
const reservesTokens = await testEnv.helpersContract.getAllReservesTokens();
|
const reservesTokens = await testEnv.helpersContract.getAllReservesTokens();
|
||||||
|
@ -138,6 +144,7 @@ export async function initializeMakeSuite() {
|
||||||
const usdcAddress = reservesTokens.find((token) => token.symbol === 'USDC')?.tokenAddress;
|
const usdcAddress = reservesTokens.find((token) => token.symbol === 'USDC')?.tokenAddress;
|
||||||
const aaveAddress = reservesTokens.find((token) => token.symbol === 'AAVE')?.tokenAddress;
|
const aaveAddress = reservesTokens.find((token) => token.symbol === 'AAVE')?.tokenAddress;
|
||||||
const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress;
|
const wethAddress = reservesTokens.find((token) => token.symbol === 'WETH')?.tokenAddress;
|
||||||
|
const rewAddress = reservesTokens.find((token) => token.symbol === 'REW')?.tokenAddress;
|
||||||
|
|
||||||
if (!aDaiAddress || !aWEthAddress) {
|
if (!aDaiAddress || !aWEthAddress) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -154,6 +161,8 @@ export async function initializeMakeSuite() {
|
||||||
testEnv.aave = await getMintableERC20(aaveAddress);
|
testEnv.aave = await getMintableERC20(aaveAddress);
|
||||||
testEnv.weth = await getWETHMocked(wethAddress);
|
testEnv.weth = await getWETHMocked(wethAddress);
|
||||||
testEnv.wethGateway = await getWETHGateway();
|
testEnv.wethGateway = await getWETHGateway();
|
||||||
|
testEnv.rew = await getRewardsToken(rewAddress);
|
||||||
|
testEnv.aRew = await getRewardsATokenMock(aRewAddress);
|
||||||
|
|
||||||
testEnv.uniswapLiquiditySwapAdapter = await getUniswapLiquiditySwapAdapter();
|
testEnv.uniswapLiquiditySwapAdapter = await getUniswapLiquiditySwapAdapter();
|
||||||
testEnv.uniswapRepayAdapter = await getUniswapRepayAdapter();
|
testEnv.uniswapRepayAdapter = await getUniswapRepayAdapter();
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { BigNumber } from 'ethers';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BigNumberValue,
|
||||||
|
ethersValueToZDBigNumber,
|
||||||
|
valueToZDBigNumber,
|
||||||
|
} from '../utils/ray-math/bignumber';
|
||||||
|
|
||||||
|
export function getRewards(
|
||||||
|
balance: BigNumber,
|
||||||
|
assetIndex: BigNumber,
|
||||||
|
userIndex: BigNumber,
|
||||||
|
precision: number = 18
|
||||||
|
): BigNumber {
|
||||||
|
return BigNumber.from(
|
||||||
|
ethersValueToZDBigNumber(balance)
|
||||||
|
.multipliedBy(ethersValueToZDBigNumber(assetIndex).minus(ethersValueToZDBigNumber(userIndex)))
|
||||||
|
.dividedBy(valueToZDBigNumber(10).exponentiatedBy(precision))
|
||||||
|
.toString()
|
||||||
|
);
|
||||||
|
}
|
112
test-suites/test-aave/helpers/rewards-distribution/verify.ts
Normal file
112
test-suites/test-aave/helpers/rewards-distribution/verify.ts
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
import { expect } from 'chai';
|
||||||
|
import { calcExpectedRewards } from '../utils/calculations';
|
||||||
|
import { SignerWithAddress } from '../make-suite';
|
||||||
|
import { ZERO_ADDRESS } from '../../../../helpers/constants';
|
||||||
|
import { tEthereumAddress } from '../../../../helpers/types';
|
||||||
|
import { IERC20Factory } from '../../../../types/IERC20Factory';
|
||||||
|
import { getRewardsAToken } from '../../../../helpers/contracts-getters';
|
||||||
|
import { BigNumber as EthersBigNumber } from '@ethersproject/bignumber';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import '../utils/math';
|
||||||
|
|
||||||
|
export const checkRewards = async (
|
||||||
|
user: SignerWithAddress,
|
||||||
|
aToken: tEthereumAddress,
|
||||||
|
block: number,
|
||||||
|
shouldReward?: boolean,
|
||||||
|
claimedToken?: tEthereumAddress,
|
||||||
|
beforeBalanceClaimedToken?: EthersBigNumber
|
||||||
|
) => {
|
||||||
|
const rewardAwareToken = await getRewardsAToken(aToken);
|
||||||
|
const rewardsAvailable = await rewardAwareToken.getRewardsTokenAddressList();
|
||||||
|
const userBalance = await rewardAwareToken.balanceOf(user.address, { blockTag: block - 1 });
|
||||||
|
const totalRewardsBefore = new Array(rewardsAvailable.length);
|
||||||
|
const userRewardsBefore = new Array(rewardsAvailable.length);
|
||||||
|
const userIndexesBefore = new Array(rewardsAvailable.length);
|
||||||
|
|
||||||
|
const totalRewardsAfter = new Array(rewardsAvailable.length);
|
||||||
|
const userRewardsAfter = new Array(rewardsAvailable.length);
|
||||||
|
const userIndexesAfter = new Array(rewardsAvailable.length);
|
||||||
|
const userExpectedRewards = new Array(rewardsAvailable.length);
|
||||||
|
|
||||||
|
for (let i = 0; i < rewardsAvailable.length; i++) {
|
||||||
|
if (rewardsAvailable[i] == ZERO_ADDRESS) break;
|
||||||
|
// Before action
|
||||||
|
|
||||||
|
totalRewardsBefore[i] = await rewardAwareToken.getLifetimeRewards(rewardsAvailable[i], {
|
||||||
|
blockTag: block - 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
userRewardsBefore[i] = await rewardAwareToken.getUserRewardsAccrued(
|
||||||
|
rewardsAvailable[i],
|
||||||
|
user.address,
|
||||||
|
{
|
||||||
|
blockTag: block - 1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
userIndexesBefore[i] = await rewardAwareToken.getUserIndex(rewardsAvailable[i], user.address, {
|
||||||
|
blockTag: block - 1,
|
||||||
|
});
|
||||||
|
// After action
|
||||||
|
totalRewardsAfter[i] = await rewardAwareToken.getLifetimeRewards(rewardsAvailable[i], {
|
||||||
|
blockTag: block,
|
||||||
|
});
|
||||||
|
|
||||||
|
userRewardsAfter[i] = await rewardAwareToken.getUserRewardsAccrued(
|
||||||
|
rewardsAvailable[i],
|
||||||
|
user.address,
|
||||||
|
{
|
||||||
|
blockTag: block,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
userIndexesAfter[i] = await rewardAwareToken.getUserIndex(rewardsAvailable[i], user.address, {
|
||||||
|
blockTag: block,
|
||||||
|
});
|
||||||
|
|
||||||
|
userExpectedRewards[i] = calcExpectedRewards(
|
||||||
|
userBalance,
|
||||||
|
userIndexesAfter[i],
|
||||||
|
userIndexesBefore[i]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Explicit check rewards when the test case expects rewards to the user
|
||||||
|
if (shouldReward) {
|
||||||
|
expect(userRewardsAfter[i]).to.be.gt('0');
|
||||||
|
expect(userRewardsAfter[i]).to.eq(
|
||||||
|
userRewardsBefore[i].add(userExpectedRewards[i]),
|
||||||
|
`User rewards for token ${rewardsAvailable[i]} does not match`
|
||||||
|
);
|
||||||
|
if (beforeBalanceClaimedToken && rewardsAvailable[i] === claimedToken) {
|
||||||
|
const reserveFactor = await rewardAwareToken.getRewardsReserveFactor();
|
||||||
|
const totalRewards = userRewardsBefore[i].add(userExpectedRewards[i]);
|
||||||
|
const priorClaimed = await rewardAwareToken.getUserClaimedRewards(
|
||||||
|
claimedToken,
|
||||||
|
user.address,
|
||||||
|
{
|
||||||
|
blockTag: block - 1,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
const totalClaim = totalRewards.sub(priorClaimed);
|
||||||
|
const treasureRewards = EthersBigNumber.from(
|
||||||
|
new BigNumber(totalClaim.toString())
|
||||||
|
.percentMul(new BigNumber(reserveFactor.toString()))
|
||||||
|
.toString()
|
||||||
|
);
|
||||||
|
const userRewards = totalClaim.sub(treasureRewards);
|
||||||
|
|
||||||
|
const afterBalance = await IERC20Factory.connect(claimedToken, user.signer).balanceOf(
|
||||||
|
user.address
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(afterBalance).to.be.eq(beforeBalanceClaimedToken.add(userRewards));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
expect(userExpectedRewards[i]).to.be.eq('0', 'This action should not reward');
|
||||||
|
expect(userRewardsBefore[i]).to.be.eq(userRewardsAfter[i], 'Rewards should stay the same');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
|
@ -1,14 +1,9 @@
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { BigNumber as BigNumberEthers } from 'ethers';
|
||||||
import { ONE_YEAR, RAY, MAX_UINT_AMOUNT, PERCENTAGE_FACTOR } from '../../../../helpers/constants';
|
import { ONE_YEAR, RAY, MAX_UINT_AMOUNT, PERCENTAGE_FACTOR } from '../../../../helpers/constants';
|
||||||
import {
|
import { IReserveParams, iAavePoolAssets, RateMode } from '../../../../helpers/types';
|
||||||
IReserveParams,
|
|
||||||
iAavePoolAssets,
|
|
||||||
RateMode,
|
|
||||||
tEthereumAddress,
|
|
||||||
} from '../../../../helpers/types';
|
|
||||||
import './math';
|
import './math';
|
||||||
import { ReserveData, UserReserveData } from './interfaces';
|
import { ReserveData, UserReserveData } from './interfaces';
|
||||||
import { expect } from 'chai';
|
|
||||||
|
|
||||||
export const strToBN = (amount: string): BigNumber => new BigNumber(amount);
|
export const strToBN = (amount: string): BigNumber => new BigNumber(amount);
|
||||||
|
|
||||||
|
@ -1244,7 +1239,9 @@ export const calcExpectedInterestRates = (
|
||||||
];
|
];
|
||||||
|
|
||||||
let stableBorrowRate: BigNumber = marketStableRate;
|
let stableBorrowRate: BigNumber = marketStableRate;
|
||||||
let variableBorrowRate: BigNumber = new BigNumber(reserveConfiguration.strategy.baseVariableBorrowRate);
|
let variableBorrowRate: BigNumber = new BigNumber(
|
||||||
|
reserveConfiguration.strategy.baseVariableBorrowRate
|
||||||
|
);
|
||||||
|
|
||||||
const optimalRate = new BigNumber(reserveConfiguration.strategy.optimalUtilizationRate);
|
const optimalRate = new BigNumber(reserveConfiguration.strategy.optimalUtilizationRate);
|
||||||
const excessRate = new BigNumber(RAY).minus(optimalRate);
|
const excessRate = new BigNumber(RAY).minus(optimalRate);
|
||||||
|
@ -1256,13 +1253,17 @@ export const calcExpectedInterestRates = (
|
||||||
stableBorrowRate = stableBorrowRate
|
stableBorrowRate = stableBorrowRate
|
||||||
.plus(reserveConfiguration.strategy.stableRateSlope1)
|
.plus(reserveConfiguration.strategy.stableRateSlope1)
|
||||||
.plus(
|
.plus(
|
||||||
new BigNumber(reserveConfiguration.strategy.stableRateSlope2).rayMul(excessUtilizationRateRatio)
|
new BigNumber(reserveConfiguration.strategy.stableRateSlope2).rayMul(
|
||||||
|
excessUtilizationRateRatio
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
variableBorrowRate = variableBorrowRate
|
variableBorrowRate = variableBorrowRate
|
||||||
.plus(reserveConfiguration.strategy.variableRateSlope1)
|
.plus(reserveConfiguration.strategy.variableRateSlope1)
|
||||||
.plus(
|
.plus(
|
||||||
new BigNumber(reserveConfiguration.strategy.variableRateSlope2).rayMul(excessUtilizationRateRatio)
|
new BigNumber(reserveConfiguration.strategy.variableRateSlope2).rayMul(
|
||||||
|
excessUtilizationRateRatio
|
||||||
|
)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
stableBorrowRate = stableBorrowRate.plus(
|
stableBorrowRate = stableBorrowRate.plus(
|
||||||
|
@ -1433,3 +1434,14 @@ const calcExpectedTotalVariableDebt = (
|
||||||
) => {
|
) => {
|
||||||
return reserveData.scaledVariableDebt.rayMul(expectedVariableDebtIndex);
|
return reserveData.scaledVariableDebt.rayMul(expectedVariableDebtIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function calcExpectedRewards(
|
||||||
|
balance: BigNumberEthers,
|
||||||
|
userIndexAfter: BigNumberEthers,
|
||||||
|
userIndexBefore: BigNumberEthers,
|
||||||
|
precision: number = 24
|
||||||
|
): BigNumberEthers {
|
||||||
|
return balance
|
||||||
|
.mul(userIndexAfter.sub(userIndexBefore))
|
||||||
|
.div(BigNumberEthers.from(10).pow(precision));
|
||||||
|
}
|
||||||
|
|
20
test-suites/test-aave/helpers/utils/ray-math/bignumber.ts
Normal file
20
test-suites/test-aave/helpers/utils/ray-math/bignumber.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { BigNumber as BigNumberEthers, BigNumberish } from 'ethers';
|
||||||
|
|
||||||
|
export type BigNumberValue = string | number | BigNumber | BigNumberEthers | BigNumberish;
|
||||||
|
|
||||||
|
export const BigNumberZD = BigNumber.clone({
|
||||||
|
DECIMAL_PLACES: 0,
|
||||||
|
ROUNDING_MODE: BigNumber.ROUND_DOWN,
|
||||||
|
});
|
||||||
|
|
||||||
|
export function valueToBigNumber(amount: BigNumberValue): BigNumber {
|
||||||
|
return new BigNumber(amount.toString());
|
||||||
|
}
|
||||||
|
export function valueToZDBigNumber(amount: BigNumberValue): BigNumber {
|
||||||
|
return new BigNumberZD(amount.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ethersValueToZDBigNumber(amount: BigNumberEthers): BigNumber {
|
||||||
|
return new BigNumberZD('0x' + amount.toHexString());
|
||||||
|
}
|
40
test-suites/test-aave/helpers/utils/ray-math/index.ts
Normal file
40
test-suites/test-aave/helpers/utils/ray-math/index.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { BigNumberValue, valueToZDBigNumber } from './bignumber';
|
||||||
|
|
||||||
|
export function getLinearCumulatedRewards(
|
||||||
|
emissionPerSecond: BigNumberValue,
|
||||||
|
lastUpdateTimestamp: BigNumberValue,
|
||||||
|
currentTimestamp: BigNumberValue
|
||||||
|
): BigNumber {
|
||||||
|
const timeDelta = valueToZDBigNumber(currentTimestamp).minus(lastUpdateTimestamp.toString());
|
||||||
|
return timeDelta.multipliedBy(emissionPerSecond.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getNormalizedDistribution(
|
||||||
|
balance: BigNumberValue,
|
||||||
|
oldIndex: BigNumberValue,
|
||||||
|
emissionPerSecond: BigNumberValue,
|
||||||
|
lastUpdateTimestamp: BigNumberValue,
|
||||||
|
currentTimestamp: BigNumberValue,
|
||||||
|
emissionEndTimestamp: BigNumberValue,
|
||||||
|
precision: number = 18
|
||||||
|
): BigNumber {
|
||||||
|
if (
|
||||||
|
balance.toString() === '0' ||
|
||||||
|
valueToZDBigNumber(lastUpdateTimestamp).gte(emissionEndTimestamp.toString())
|
||||||
|
) {
|
||||||
|
return valueToZDBigNumber(oldIndex);
|
||||||
|
}
|
||||||
|
const linearReward = getLinearCumulatedRewards(
|
||||||
|
emissionPerSecond,
|
||||||
|
lastUpdateTimestamp,
|
||||||
|
valueToZDBigNumber(currentTimestamp).gte(emissionEndTimestamp.toString())
|
||||||
|
? emissionEndTimestamp
|
||||||
|
: currentTimestamp
|
||||||
|
);
|
||||||
|
|
||||||
|
return linearReward
|
||||||
|
.multipliedBy(valueToZDBigNumber(10).exponentiatedBy(precision))
|
||||||
|
.div(balance.toString())
|
||||||
|
.plus(oldIndex.toString());
|
||||||
|
}
|
59
test-suites/test-aave/helpers/utils/ray-math/ray-math.ts
Normal file
59
test-suites/test-aave/helpers/utils/ray-math/ray-math.ts
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { BigNumberValue, valueToZDBigNumber } from './bignumber';
|
||||||
|
|
||||||
|
export const WAD = valueToZDBigNumber(10).pow(18);
|
||||||
|
export const HALF_WAD = WAD.dividedBy(2);
|
||||||
|
|
||||||
|
export const RAY = valueToZDBigNumber(10).pow(27);
|
||||||
|
export const HALF_RAY = RAY.dividedBy(2);
|
||||||
|
|
||||||
|
export const WAD_RAY_RATIO = valueToZDBigNumber(10).pow(9);
|
||||||
|
|
||||||
|
export function wadMul(a: BigNumberValue, b: BigNumberValue): BigNumber {
|
||||||
|
return HALF_WAD.plus(valueToZDBigNumber(a).multipliedBy(b.toString())).div(WAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wadDiv(a: BigNumberValue, b: BigNumberValue): BigNumber {
|
||||||
|
const halfB = valueToZDBigNumber(b).div(2);
|
||||||
|
|
||||||
|
return halfB.plus(valueToZDBigNumber(a).multipliedBy(WAD)).div(b.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rayMul(a: BigNumberValue, b: BigNumberValue): BigNumber {
|
||||||
|
return HALF_RAY.plus(valueToZDBigNumber(a).multipliedBy(b.toString())).div(RAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rayDiv(a: BigNumberValue, b: BigNumberValue): BigNumber {
|
||||||
|
const halfB = valueToZDBigNumber(b).div(2);
|
||||||
|
|
||||||
|
return halfB.plus(valueToZDBigNumber(a).multipliedBy(RAY)).div(b.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rayToWad(a: BigNumberValue): BigNumber {
|
||||||
|
const halfRatio = valueToZDBigNumber(WAD_RAY_RATIO).div(2);
|
||||||
|
|
||||||
|
return halfRatio.plus(a.toString()).div(WAD_RAY_RATIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function wadToRay(a: BigNumberValue): BigNumber {
|
||||||
|
return valueToZDBigNumber(a).multipliedBy(WAD_RAY_RATIO).decimalPlaces(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rayPow(a: BigNumberValue, p: BigNumberValue): BigNumber {
|
||||||
|
let x = valueToZDBigNumber(a);
|
||||||
|
let n = valueToZDBigNumber(p);
|
||||||
|
let z = !n.modulo(2).eq(0) ? x : valueToZDBigNumber(RAY);
|
||||||
|
|
||||||
|
for (n = n.div(2); !n.eq(0); n = n.div(2)) {
|
||||||
|
x = rayMul(x, x);
|
||||||
|
|
||||||
|
if (!n.modulo(2).eq(0)) {
|
||||||
|
z = rayMul(z, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rayToDecimal(a: BigNumberValue): BigNumber {
|
||||||
|
return valueToZDBigNumber(a).dividedBy(RAY);
|
||||||
|
}
|
521
test-suites/test-aave/rewardAwareAToken.spec.ts
Normal file
521
test-suites/test-aave/rewardAwareAToken.spec.ts
Normal file
|
@ -0,0 +1,521 @@
|
||||||
|
import BigNumberJs from 'bignumber.js';
|
||||||
|
import { BigNumber } from 'ethers';
|
||||||
|
import { parseEther } from 'ethers/lib/utils';
|
||||||
|
import { MAX_UINT_AMOUNT } from '../../helpers/constants';
|
||||||
|
import { evmRevert, evmSnapshot, increaseTime } from '../../helpers/misc-utils';
|
||||||
|
import { makeSuite, SignerWithAddress, TestEnv } from './helpers/make-suite';
|
||||||
|
import { checkRewards } from './helpers/rewards-distribution/verify';
|
||||||
|
|
||||||
|
const chai = require('chai');
|
||||||
|
const { expect } = chai;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev REW is a mocked mintable token named RewardsToken.sol with an emission rate of 1 REW per second that can be deposited using a RewardsAwareAToken implementation named RewardsATokenMock.sol
|
||||||
|
* The distribution of REW happens at `claim`, but there is also a `updateMintableEmission` functions that updates the state of the distribution of 1 user but does not claim.
|
||||||
|
*/
|
||||||
|
|
||||||
|
makeSuite('Reward Aware AToken', (testEnv: TestEnv) => {
|
||||||
|
let initTimestamp;
|
||||||
|
let evmSnapshotId;
|
||||||
|
|
||||||
|
before('Initializing configuration', async () => {
|
||||||
|
// Sets BigNumber for this suite, instead of globally
|
||||||
|
BigNumberJs.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumberJs.ROUND_DOWN });
|
||||||
|
});
|
||||||
|
|
||||||
|
after('Reset', () => {
|
||||||
|
// Reset BigNumber
|
||||||
|
BigNumberJs.config({ DECIMAL_PLACES: 20, ROUNDING_MODE: BigNumberJs.ROUND_HALF_UP });
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
initTimestamp = await testEnv.rew.INIT_TIMESTAMP();
|
||||||
|
evmSnapshotId = await evmSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await evmRevert(evmSnapshotId);
|
||||||
|
});
|
||||||
|
|
||||||
|
const mintAndDeposit = async (
|
||||||
|
key: SignerWithAddress,
|
||||||
|
shouldReward?: boolean,
|
||||||
|
amountSize?: BigNumber
|
||||||
|
) => {
|
||||||
|
const { rew, aRew, pool } = testEnv;
|
||||||
|
const amount = amountSize || parseEther('1');
|
||||||
|
const userATokenBalanceBeforeDeposit = await aRew.balanceOf(key.address);
|
||||||
|
|
||||||
|
// Mint REW to user
|
||||||
|
await rew.connect(key.signer).mint(amount);
|
||||||
|
|
||||||
|
// Approve and Deposit REW to pool and mint
|
||||||
|
await rew.connect(key.signer).approve(pool.address, amount);
|
||||||
|
|
||||||
|
const txDeposit = await pool.connect(key.signer).deposit(rew.address, amount, key.address, '0');
|
||||||
|
|
||||||
|
expect(Promise.resolve(txDeposit)).emit(aRew, 'Mint');
|
||||||
|
|
||||||
|
const userBalanceAfterDeposit = await rew.balanceOf(key.address);
|
||||||
|
const userATokenBalanceAfterDeposit = await aRew.balanceOf(key.address);
|
||||||
|
|
||||||
|
expect(userATokenBalanceAfterDeposit)
|
||||||
|
.to.be.eq(
|
||||||
|
userATokenBalanceBeforeDeposit.add(amount),
|
||||||
|
'User aToken balance should be equal the amount deposited'
|
||||||
|
)
|
||||||
|
.and.gt('0', 'User aToken balance should be greater than zero');
|
||||||
|
expect(userBalanceAfterDeposit).to.be.eq('0', 'Token balance should be zero');
|
||||||
|
if (!txDeposit.blockNumber) {
|
||||||
|
throw 'missing block number';
|
||||||
|
}
|
||||||
|
// Check all token rewards
|
||||||
|
await checkRewards(key, aRew.address, txDeposit.blockNumber, shouldReward);
|
||||||
|
};
|
||||||
|
|
||||||
|
const claim = async (user: SignerWithAddress, skipRewardChecks?: boolean) => {
|
||||||
|
skipRewardChecks = true;
|
||||||
|
|
||||||
|
const { rew, aRew } = testEnv;
|
||||||
|
|
||||||
|
// Claim all the rewards from aToken
|
||||||
|
const txClaim = await aRew.connect(user.signer).claim(rew.address);
|
||||||
|
await expect(Promise.resolve(txClaim)).to.emit(aRew, 'Claim');
|
||||||
|
|
||||||
|
// Calculate expected rewards
|
||||||
|
if (!txClaim.blockNumber) {
|
||||||
|
throw 'Block number missing from tx';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipRewardChecks) {
|
||||||
|
// Check all token rewards
|
||||||
|
await checkRewards(user, aRew.address, txClaim.blockNumber, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('Deposits: mints', async () => {
|
||||||
|
it('User1 deposits Reward Aware Token to Lending Pool', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
} = testEnv;
|
||||||
|
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Other users deposits Reward Aware Token to Lending Pool', async () => {
|
||||||
|
const {
|
||||||
|
users: [, user2, user3, user4],
|
||||||
|
} = testEnv;
|
||||||
|
|
||||||
|
await mintAndDeposit(user2);
|
||||||
|
await mintAndDeposit(user3);
|
||||||
|
await mintAndDeposit(user4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('User1 deposits multiple time Reward Aware Token to Lending Pool', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
} = testEnv;
|
||||||
|
|
||||||
|
await mintAndDeposit(user1, false, parseEther('2'));
|
||||||
|
await mintAndDeposit(user1, true, parseEther('12'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Withdrawals: burns', async () => {
|
||||||
|
it('User1 deposits Reward Aware Token to Lending Pool', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
pool,
|
||||||
|
} = testEnv;
|
||||||
|
|
||||||
|
// Deposits
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Burn/Withdraw
|
||||||
|
await aRew.approve(pool.address, MAX_UINT_AMOUNT);
|
||||||
|
await pool.connect(user1.signer).withdraw(rew.address, MAX_UINT_AMOUNT, user1.address);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Claim rewards', async () => {
|
||||||
|
it('User1 claims 100% portion of REW via the aToken contract', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
rew,
|
||||||
|
aRew,
|
||||||
|
} = testEnv;
|
||||||
|
// User1 deposits
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
// Check rewards for aToken at rew
|
||||||
|
const token = await aRew.getRewardsTokenAddress('0');
|
||||||
|
const aTokenRewards = await rew.getClaimableRewards(aRew.address);
|
||||||
|
// Check rewards for user at aRew
|
||||||
|
const userRewards = await aRew.getClaimableRewards(rew.address, user1.address);
|
||||||
|
// Expect user rewards to be the same as aToken rewards due 100%
|
||||||
|
expect(aTokenRewards).to.be.eq(
|
||||||
|
userRewards,
|
||||||
|
'Rewards should be the same due user holds 100% of RewardsAware distribution'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Claims and check rewards
|
||||||
|
await claim(user1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Two users with half the portion of REW via the aToken contract', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1, user2],
|
||||||
|
rew,
|
||||||
|
aRew,
|
||||||
|
} = testEnv;
|
||||||
|
// User1 and user2 deposits
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
await mintAndDeposit(user2);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
// Check rewards for aToken at rew
|
||||||
|
const aTokenRewards = await rew.getClaimableRewards(aRew.address);
|
||||||
|
|
||||||
|
// Check rewards for user1 at aRew
|
||||||
|
const user1Rewards = await aRew.getClaimableRewards(rew.address, user1.address);
|
||||||
|
|
||||||
|
// Check rewards for user2 at aRew
|
||||||
|
const user2Rewards = await aRew.getClaimableRewards(rew.address, user2.address);
|
||||||
|
|
||||||
|
// Expect user rewards to be the same as aToken rewards
|
||||||
|
expect(aTokenRewards).to.be.eq(
|
||||||
|
user1Rewards.add(user2Rewards),
|
||||||
|
'Rewards should be the same of all users of RewardsAware distribution'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Claims and check rewards
|
||||||
|
await claim(user1);
|
||||||
|
await claim(user2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Four users with different portions of REW via the aToken contract', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1, user2, user3, user4],
|
||||||
|
rew,
|
||||||
|
aRew,
|
||||||
|
} = testEnv;
|
||||||
|
// Deposits
|
||||||
|
await mintAndDeposit(user1, false, parseEther('1'));
|
||||||
|
await mintAndDeposit(user2, false, parseEther('2.5'));
|
||||||
|
await mintAndDeposit(user3, false, parseEther('4.7'));
|
||||||
|
await mintAndDeposit(user4, false, parseEther('0.31'));
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
// Claims and check rewards
|
||||||
|
await claim(user1);
|
||||||
|
await claim(user2);
|
||||||
|
await claim(user3);
|
||||||
|
await claim(user4);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(2713);
|
||||||
|
|
||||||
|
// Claims and check rewards
|
||||||
|
await claim(user1);
|
||||||
|
await claim(user2);
|
||||||
|
await claim(user3);
|
||||||
|
await claim(user4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Two users with half the portion of REW via the aToken contract, one burns and them claims', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1, user2],
|
||||||
|
rew,
|
||||||
|
aRew,
|
||||||
|
pool,
|
||||||
|
} = testEnv;
|
||||||
|
|
||||||
|
// User1 and user2 deposits
|
||||||
|
await mintAndDeposit(user1, false, parseEther('1000'));
|
||||||
|
await mintAndDeposit(user2, false, parseEther('1000'));
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
// Claims and check rewards
|
||||||
|
await claim(user1);
|
||||||
|
await claim(user2);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
// Burn/Withdraw to update current lifetime rewards state
|
||||||
|
await aRew.approve(pool.address, MAX_UINT_AMOUNT);
|
||||||
|
await pool.connect(user1.signer).withdraw(rew.address, MAX_UINT_AMOUNT, user1.address);
|
||||||
|
|
||||||
|
// Claims
|
||||||
|
await claim(user1);
|
||||||
|
await claim(user2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Getters', () => {
|
||||||
|
describe('getClaimableRewards', () => {
|
||||||
|
it('Rewards should be zero if user with no balance', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
|
||||||
|
const rewards = await aRew.getClaimableRewards(rew.address, user1.address);
|
||||||
|
expect(rewards).eq('0', 'Rewards should be zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Rewards should be available after time travel', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
const rewards = await aRew.getClaimableRewards(rew.address, user1.address);
|
||||||
|
expect(rewards).gt('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getUserLifetimeRewardsAccrued', () => {
|
||||||
|
it('User lifetime rewards should be zero if no deposit', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserRewardsAccrued(rew.address, user1.address);
|
||||||
|
expect(rewards).eq('0', 'Rewards should be zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('User lifetime rewards should be zero if deposit due state is not updated', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserRewardsAccrued(rew.address, user1.address);
|
||||||
|
expect(rewards).eq('0', 'Rewards should be zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('User should have some lifetime rewards if deposit again due state is updated', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
await mintAndDeposit(user1, true);
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserRewardsAccrued(rew.address, user1.address);
|
||||||
|
expect(rewards).gt('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('User should have some lifetime rewards if claims due state is updated', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
await claim(user1);
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserRewardsAccrued(rew.address, user1.address);
|
||||||
|
expect(rewards).gt('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getUserIndex', () => {
|
||||||
|
it('User index should be zero if no deposit', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserIndex(rew.address, user1.address);
|
||||||
|
expect(rewards).eq('0', 'Rewards should be zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('User lifetime rewards should be zero if deposit due state is not updated', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserIndex(rew.address, user1.address);
|
||||||
|
expect(rewards).eq('0', 'Rewards should be zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('User should have some lifetime rewards if deposit again due state is updated', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
await mintAndDeposit(user1, true);
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserIndex(rew.address, user1.address);
|
||||||
|
expect(rewards).gt('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('User should have some lifetime rewards if claims due state is updated', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
await claim(user1);
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserIndex(rew.address, user1.address);
|
||||||
|
expect(rewards).gt('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getUserClaimedRewards', () => {
|
||||||
|
it('User should NOT have claimed rewards if didnt claim', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserIndex(rew.address, user1.address);
|
||||||
|
expect(rewards).eq('0', 'Rewards should be zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('User should have claimed rewards if claims', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
await claim(user1);
|
||||||
|
|
||||||
|
const rewards = await aRew.getUserIndex(rew.address, user1.address);
|
||||||
|
expect(rewards).gt('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getLifetimeRewards', () => {
|
||||||
|
it('The aToken Tifetime rewards should be zero if there is no deposits', async () => {
|
||||||
|
const { aRew, rew } = testEnv;
|
||||||
|
|
||||||
|
const rewards = await aRew.getLifetimeRewards(rew.address);
|
||||||
|
expect(rewards).eq('0', 'Rewards should be zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('The aToken lifetime rewards should be zero at init', async () => {
|
||||||
|
const { aRew, rew } = testEnv;
|
||||||
|
|
||||||
|
const rewards = await aRew.getLifetimeRewards(rew.address);
|
||||||
|
expect(rewards).eq('0', 'Rewards should be zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('The aToken lifetime rewards should update if there is further actions: deposit', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
// Deposit again to update current lifetime rewards state
|
||||||
|
await mintAndDeposit(user1, true);
|
||||||
|
|
||||||
|
const rewards = await aRew.getLifetimeRewards(rew.address);
|
||||||
|
expect(rewards).gte('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('The aToken lifetime rewards should update if there is further actions: claim', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
// Claim to update current lifetime rewards state
|
||||||
|
await claim(user1);
|
||||||
|
|
||||||
|
const rewards = await aRew.getLifetimeRewards(rew.address);
|
||||||
|
expect(rewards).gte('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('The aToken lifetime rewards should update if there is further actions: burn', async () => {
|
||||||
|
const {
|
||||||
|
users: [user1],
|
||||||
|
aRew,
|
||||||
|
rew,
|
||||||
|
pool,
|
||||||
|
} = testEnv;
|
||||||
|
await mintAndDeposit(user1);
|
||||||
|
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await increaseTime(1000);
|
||||||
|
|
||||||
|
// Burn/Withdraw to update current lifetime rewards state
|
||||||
|
await aRew.approve(pool.address, MAX_UINT_AMOUNT);
|
||||||
|
await pool.connect(user1.signer).withdraw(rew.address, MAX_UINT_AMOUNT, user1.address);
|
||||||
|
|
||||||
|
const rewards = await aRew.getLifetimeRewards(rew.address);
|
||||||
|
expect(rewards).gte('0', 'Rewards should be greater than zero');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getRewardsToken', () => {
|
||||||
|
it('The getter should return the current token reward address', async () => {
|
||||||
|
const { aRew, rew } = testEnv;
|
||||||
|
const rewardToken = await aRew.getRewardsTokenAddress(0);
|
||||||
|
expect(rewardToken).to.be.equal(rew.address);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -26,7 +26,8 @@ import {
|
||||||
deployUniswapLiquiditySwapAdapter,
|
deployUniswapLiquiditySwapAdapter,
|
||||||
deployUniswapRepayAdapter,
|
deployUniswapRepayAdapter,
|
||||||
deployFlashLiquidationAdapter,
|
deployFlashLiquidationAdapter,
|
||||||
authorizeWETHGateway
|
authorizeWETHGateway,
|
||||||
|
deployATokenImplementations,
|
||||||
} from '../../helpers/contracts-deployments';
|
} from '../../helpers/contracts-deployments';
|
||||||
import { Signer } from 'ethers';
|
import { Signer } from 'ethers';
|
||||||
import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types';
|
import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types';
|
||||||
|
@ -94,6 +95,14 @@ const deployAllMockTokens = async (deployer: Signer) => {
|
||||||
const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
console.time('setup');
|
console.time('setup');
|
||||||
const aaveAdmin = await deployer.getAddress();
|
const aaveAdmin = await deployer.getAddress();
|
||||||
|
const config = loadPoolConfig(ConfigNames.Amm);
|
||||||
|
const {
|
||||||
|
ATokenNamePrefix,
|
||||||
|
StableDebtTokenNamePrefix,
|
||||||
|
VariableDebtTokenNamePrefix,
|
||||||
|
SymbolPrefix,
|
||||||
|
ReservesConfig,
|
||||||
|
} = config;
|
||||||
|
|
||||||
const mockTokens = await deployAllMockTokens(deployer);
|
const mockTokens = await deployAllMockTokens(deployer);
|
||||||
|
|
||||||
|
@ -229,8 +238,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
lendingRateOracle,
|
lendingRateOracle,
|
||||||
aaveAdmin
|
aaveAdmin
|
||||||
);
|
);
|
||||||
|
await deployATokenImplementations(ConfigNames.Amm, ReservesConfig);
|
||||||
const reservesParams = getReservesConfigByPool(AavePools.amm);
|
|
||||||
|
|
||||||
const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address);
|
const testHelpers = await deployAaveProtocolDataProvider(addressesProvider.address);
|
||||||
|
|
||||||
|
@ -239,18 +247,10 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
|
|
||||||
console.log('Initialize configuration');
|
console.log('Initialize configuration');
|
||||||
|
|
||||||
const config = loadPoolConfig(ConfigNames.Amm);
|
|
||||||
|
|
||||||
const {
|
|
||||||
ATokenNamePrefix,
|
|
||||||
StableDebtTokenNamePrefix,
|
|
||||||
VariableDebtTokenNamePrefix,
|
|
||||||
SymbolPrefix,
|
|
||||||
} = config;
|
|
||||||
const treasuryAddress = await getTreasuryAddress(config);
|
const treasuryAddress = await getTreasuryAddress(config);
|
||||||
|
|
||||||
await initReservesByHelper(
|
await initReservesByHelper(
|
||||||
reservesParams,
|
ReservesConfig,
|
||||||
allReservesAddresses,
|
allReservesAddresses,
|
||||||
ATokenNamePrefix,
|
ATokenNamePrefix,
|
||||||
StableDebtTokenNamePrefix,
|
StableDebtTokenNamePrefix,
|
||||||
|
@ -259,9 +259,10 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => {
|
||||||
admin,
|
admin,
|
||||||
treasuryAddress,
|
treasuryAddress,
|
||||||
ZERO_ADDRESS,
|
ZERO_ADDRESS,
|
||||||
|
ConfigNames.Amm,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
await configureReservesByHelper(reservesParams, allReservesAddresses, testHelpers, admin);
|
await configureReservesByHelper(ReservesConfig, allReservesAddresses, testHelpers, admin);
|
||||||
|
|
||||||
const collateralManager = await deployLendingPoolCollateralManager();
|
const collateralManager = await deployLendingPoolCollateralManager();
|
||||||
await waitForTx(
|
await waitForTx(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user