Merge branch 'master' into feat/add-compile-prior-tests

This commit is contained in:
David Racero 2021-05-11 12:35:15 +02:00 committed by GitHub
commit 6c0bbadacb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
216 changed files with 26470 additions and 9409 deletions

37
.github/workflows/node.js.yml vendored Normal file
View File

@ -0,0 +1,37 @@
name: Build
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
- name: Test
run: npm run ci:test
# - name: Coverage
# run: npm run coverage
# - uses: codecov/codecov-action@v1
# with:
# fail_ci_if_error: true

View File

@ -1,5 +1,22 @@
stages:
- checks
- prepare
- publish
variables:
IMAGE: ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA}
lint:
stage: checks
tags:
- aave-build-runner
before_script:
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml build
script:
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run prettier:check
after_script:
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down
test:
stage: checks
@ -12,7 +29,9 @@ test:
after_script:
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down
only:
- master
- merge_requests
deploy-mainnet-fork:
tags:
- aave-build-runner
@ -24,6 +43,9 @@ deploy-mainnet-fork:
after_script:
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml run contracts-env npm run ci:clean
- docker-compose -p ${CI_JOB_ID} -f docker-compose.test.yml down
only:
- master
- merge_requests
certora-test:
stage: checks
@ -40,3 +62,31 @@ certora-test:
- certoraRun specs/harness/StableDebtTokenHarness.sol:StableDebtTokenHarness --solc_args "['--optimize']" --verify StableDebtTokenHarness:specs/StableDebtToken.spec --settings -assumeUnwindCond,-b=4 --cache StableDebtToken --cloud
- certoraRun specs/harness/UserConfigurationHarness.sol --verify UserConfigurationHarness:specs/UserConfiguration.spec --solc_args "['--optimize']" --settings -useBitVectorTheory --cache UserConfiguration --cloud
- certoraRun contracts/protocol/tokenization/VariableDebtToken.sol:VariableDebtToken specs/harness/LendingPoolHarnessForVariableDebtToken.sol --solc_args "['--optimize']" --link VariableDebtToken:POOL=LendingPoolHarnessForVariableDebtToken --verify VariableDebtToken:specs/VariableDebtToken.spec --settings -assumeUnwindCond,-useNonLinearArithmetic,-b=4 --cache VariableDebtToken --cloud
only:
- master
- merge_requests
prepare:
stage: prepare
tags:
- docker-builder
script:
- docker build -t ${IMAGE} .
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN $CI_REGISTRY
- docker push ${IMAGE}
only:
- master
publish:
image: ${IMAGE}
tags:
- docker
stage: publish
script:
- npm ci
- echo //registry.npmjs.org/:_authToken=${NPM_V2_PACKAGES_TOKEN} > .npmrc
- npm run compile
- ${VERSION}
- npm publish --access public
only:
- master

View File

@ -1,3 +1,5 @@
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
[![Build pass](https://github.com/AAVE/protocol-v2/actions/workflows/node.js.yml/badge.svg)](https://github.com/aave/protocol-v2/actions/workflows/node.js.yml)
```
.///. .///. //. .// `/////////////-
`++:++` .++:++` :++` `++: `++:......---.`
@ -40,6 +42,37 @@ A more detailed and technical description of the protocol can be found in this r
You can join at the [Discord](http://aave.com/discord) channel or at the [Governance Forum](https://governance.aave.com/) for asking questions about the protocol or talk about Aave with other peers.
## Getting Started
You can install `@aave/protocol-v2` as an NPM package in your Hardhat, Buidler or Truffle project to import the contracts and interfaces:
`npm install @aave/protocol-v2`
Import at Solidity files:
```
import {ILendingPool} from "@aave/protocol-v2/contracts/interfaces/ILendingPool.sol";
contract Misc {
function deposit(address pool, address token, address user, uint256 amount) public {
ILendingPool(pool).deposit(token, amount, user, 0);
{...}
}
}
```
The JSON artifacts with the ABI and Bytecode are also included into the bundled NPM package at `artifacts/` directory.
Import JSON file via Node JS `require`:
```
const LendingPoolV2Artifact = require('@aave/protocol-v2/artifacts/contracts/protocol/lendingpool/LendingPool.sol/LendingPool.json');
// Log the ABI into console
console.log(LendingPoolV2Artifact.abi)
```
## Setup
The repository uses Docker Compose to manage sensitive keys and load the configuration. Prior any action like test or deploy, you must run `docker-compose up` to start the `contracts-env` container, and then connect to the container console via `docker-compose exec contracts-env bash`.

Binary file not shown.

View File

@ -24,7 +24,6 @@ import {IBaseUniswapAdapter} from './interfaces/IBaseUniswapAdapter.sol';
abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapter, Ownable {
using SafeMath for uint256;
using PercentageMath for uint256;
using SafeERC20 for IERC20;
// Max slippage percent allowed
@ -349,13 +348,16 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
if (reserveIn == reserveOut) {
uint256 reserveDecimals = _getDecimals(reserveIn);
address[] memory path = new address[](1);
path[0] = reserveIn;
return
AmountCalc(
finalAmountIn,
finalAmountIn.mul(10**18).div(amountIn),
_calcUsdValue(reserveIn, amountIn, reserveDecimals),
_calcUsdValue(reserveIn, finalAmountIn, reserveDecimals),
[reserveIn]
path
);
}
@ -437,13 +439,16 @@ abstract contract BaseUniswapAdapter is FlashLoanReceiverBase, IBaseUniswapAdapt
// Add flash loan fee
uint256 amountIn = amountOut.add(amountOut.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000));
uint256 reserveDecimals = _getDecimals(reserveIn);
address[] memory path = new address[](1);
path[0] = reserveIn;
return
AmountCalc(
amountIn,
amountOut.mul(10**18).div(amountIn),
_calcUsdValue(reserveIn, amountIn, reserveDecimals),
_calcUsdValue(reserveIn, amountOut, reserveDecimals),
[reserveIn]
path
);
}

View File

@ -0,0 +1,184 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {BaseUniswapAdapter} from './BaseUniswapAdapter.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {IUniswapV2Router02} from '../interfaces/IUniswapV2Router02.sol';
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {DataTypes} from '../protocol/libraries/types/DataTypes.sol';
import {Helpers} from '../protocol/libraries/helpers/Helpers.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
import {IAToken} from '../interfaces/IAToken.sol';
import {ReserveConfiguration} from '../protocol/libraries/configuration/ReserveConfiguration.sol';
/**
* @title UniswapLiquiditySwapAdapter
* @notice Uniswap V2 Adapter to swap liquidity.
* @author Aave
**/
contract FlashLiquidationAdapter is BaseUniswapAdapter {
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
uint256 internal constant LIQUIDATION_CLOSE_FACTOR_PERCENT = 5000;
struct LiquidationParams {
address collateralAsset;
address borrowedAsset;
address user;
uint256 debtToCover;
bool useEthPath;
}
struct LiquidationCallLocalVars {
uint256 initFlashBorrowedBalance;
uint256 diffFlashBorrowedBalance;
uint256 initCollateralBalance;
uint256 diffCollateralBalance;
uint256 flashLoanDebt;
uint256 soldAmount;
uint256 remainingTokens;
uint256 borrowedAssetLeftovers;
}
constructor(
ILendingPoolAddressesProvider addressesProvider,
IUniswapV2Router02 uniswapRouter,
address wethAddress
) public BaseUniswapAdapter(addressesProvider, uniswapRouter, wethAddress) {}
/**
* @dev Liquidate a non-healthy position collateral-wise, with a Health Factor below 1, using Flash Loan and Uniswap to repay flash loan premium.
* - The caller (liquidator) with a flash loan covers `debtToCover` amount of debt of the user getting liquidated, and receives
* a proportionally amount of the `collateralAsset` plus a bonus to cover market risk minus the flash loan premium.
* @param assets Address of asset to be swapped
* @param amounts Amount of the asset to be swapped
* @param premiums Fee of the flash loan
* @param initiator Address of the caller
* @param params Additional variadic field to include extra params. Expected parameters:
* address collateralAsset The collateral asset to release and will be exchanged to pay the flash loan premium
* address borrowedAsset The asset that must be covered
* address user The user address with a Health Factor below 1
* uint256 debtToCover The amount of debt to cover
* bool useEthPath Use WETH as connector path between the collateralAsset and borrowedAsset at Uniswap
*/
function executeOperation(
address[] calldata assets,
uint256[] calldata amounts,
uint256[] calldata premiums,
address initiator,
bytes calldata params
) external override returns (bool) {
require(msg.sender == address(LENDING_POOL), 'CALLER_MUST_BE_LENDING_POOL');
LiquidationParams memory decodedParams = _decodeParams(params);
require(assets.length == 1 && assets[0] == decodedParams.borrowedAsset, 'INCONSISTENT_PARAMS');
_liquidateAndSwap(
decodedParams.collateralAsset,
decodedParams.borrowedAsset,
decodedParams.user,
decodedParams.debtToCover,
decodedParams.useEthPath,
amounts[0],
premiums[0],
initiator
);
return true;
}
/**
* @dev
* @param collateralAsset The collateral asset to release and will be exchanged to pay the flash loan premium
* @param borrowedAsset The asset that must be covered
* @param user The user address with a Health Factor below 1
* @param debtToCover The amount of debt to coverage, can be max(-1) to liquidate all possible debt
* @param useEthPath true if the swap needs to occur using ETH in the routing, false otherwise
* @param flashBorrowedAmount Amount of asset requested at the flash loan to liquidate the user position
* @param premium Fee of the requested flash loan
* @param initiator Address of the caller
*/
function _liquidateAndSwap(
address collateralAsset,
address borrowedAsset,
address user,
uint256 debtToCover,
bool useEthPath,
uint256 flashBorrowedAmount,
uint256 premium,
address initiator
) internal {
LiquidationCallLocalVars memory vars;
vars.initCollateralBalance = IERC20(collateralAsset).balanceOf(address(this));
if (collateralAsset != borrowedAsset) {
vars.initFlashBorrowedBalance = IERC20(borrowedAsset).balanceOf(address(this));
// Track leftover balance to rescue funds in case of external transfers into this contract
vars.borrowedAssetLeftovers = vars.initFlashBorrowedBalance.sub(flashBorrowedAmount);
}
vars.flashLoanDebt = flashBorrowedAmount.add(premium);
// Approve LendingPool to use debt token for liquidation
IERC20(borrowedAsset).approve(address(LENDING_POOL), debtToCover);
// Liquidate the user position and release the underlying collateral
LENDING_POOL.liquidationCall(collateralAsset, borrowedAsset, user, debtToCover, false);
// Discover the liquidated tokens
uint256 collateralBalanceAfter = IERC20(collateralAsset).balanceOf(address(this));
// Track only collateral released, not current asset balance of the contract
vars.diffCollateralBalance = collateralBalanceAfter.sub(vars.initCollateralBalance);
if (collateralAsset != borrowedAsset) {
// Discover flash loan balance after the liquidation
uint256 flashBorrowedAssetAfter = IERC20(borrowedAsset).balanceOf(address(this));
// Use only flash loan borrowed assets, not current asset balance of the contract
vars.diffFlashBorrowedBalance = flashBorrowedAssetAfter.sub(vars.borrowedAssetLeftovers);
// Swap released collateral into the debt asset, to repay the flash loan
vars.soldAmount = _swapTokensForExactTokens(
collateralAsset,
borrowedAsset,
vars.diffCollateralBalance,
vars.flashLoanDebt.sub(vars.diffFlashBorrowedBalance),
useEthPath
);
vars.remainingTokens = vars.diffCollateralBalance.sub(vars.soldAmount);
} else {
vars.remainingTokens = vars.diffCollateralBalance.sub(premium);
}
// Allow repay of flash loan
IERC20(borrowedAsset).approve(address(LENDING_POOL), vars.flashLoanDebt);
// Transfer remaining tokens to initiator
if (vars.remainingTokens > 0) {
IERC20(collateralAsset).transfer(initiator, vars.remainingTokens);
}
}
/**
* @dev Decodes the information encoded in the flash loan params
* @param params Additional variadic field to include extra params. Expected parameters:
* address collateralAsset The collateral asset to claim
* address borrowedAsset The asset that must be covered and will be exchanged to pay the flash loan premium
* address user The user address with a Health Factor below 1
* uint256 debtToCover The amount of debt to cover
* bool useEthPath Use WETH as connector path between the collateralAsset and borrowedAsset at Uniswap
* @return LiquidationParams struct containing decoded params
*/
function _decodeParams(bytes memory params) internal pure returns (LiquidationParams memory) {
(
address collateralAsset,
address borrowedAsset,
address user,
uint256 debtToCover,
bool useEthPath
) = abi.decode(params, (address, address, address, uint256, bool));
return LiquidationParams(collateralAsset, borrowedAsset, user, debtToCover, useEthPath);
}
}

View File

@ -234,6 +234,7 @@ contract UniswapRepayAdapter is BaseUniswapAdapter {
* uint8 v V param for the permit signature
* bytes32 r R param for the permit signature
* bytes32 s S param for the permit signature
* bool useEthPath use WETH path route
* @return RepayParams struct containing decoded params
*/
function _decodeParams(bytes memory params) internal pure returns (RepayParams memory) {

View File

@ -12,11 +12,11 @@ pragma solidity 0.6.12;
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal virtual view returns (address payable) {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal virtual view returns (bytes memory) {
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}

View File

@ -95,14 +95,14 @@ contract ERC20 is Context, IERC20 {
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public override view returns (uint256) {
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public override view returns (uint256) {
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
@ -124,9 +124,9 @@ contract ERC20 is Context, IERC20 {
*/
function allowance(address owner, address spender)
public
view
virtual
override
view
returns (uint256)
{
return _allowances[owner][spender];

View File

@ -24,7 +24,8 @@ contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
bytes32 internal constant ADMIN_SLOT =
0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Modifier to check whether the `msg.sender` is the admin.

View File

@ -22,13 +22,14 @@ contract BaseUpgradeabilityProxy is Proxy {
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
bytes32 internal constant IMPLEMENTATION_SLOT =
0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation.
* @return impl Address of the current implementation
*/
function _implementation() internal override view returns (address impl) {
function _implementation() internal view override returns (address impl) {
bytes32 slot = IMPLEMENTATION_SLOT;
//solium-disable-next-line
assembly {

View File

@ -20,7 +20,7 @@ abstract contract Proxy {
/**
* @return The Address of the implementation.
*/
function _implementation() internal virtual view returns (address);
function _implementation() internal view virtual returns (address);
/**
* @dev Delegates execution to an implementation contract.

View File

@ -20,6 +20,20 @@ contract ATokensAndRatesHelper is Ownable {
address private poolConfigurator;
event deployedContracts(address aToken, address strategy);
struct InitDeploymentInput {
address asset;
uint256[6] rates;
}
struct ConfigureReserveInput {
address asset;
uint256 baseLTV;
uint256 liquidationThreshold;
uint256 liquidationBonus;
uint256 reserveFactor;
bool stableBorrowingEnabled;
}
constructor(
address payable _pool,
address _addressesProvider,
@ -30,93 +44,40 @@ contract ATokensAndRatesHelper is Ownable {
poolConfigurator = _poolConfigurator;
}
function initDeployment(
address[] calldata assets,
string[] calldata symbols,
uint256[6][] calldata rates,
address treasuryAddress,
address incentivesController
) external onlyOwner {
require(assets.length == symbols.length, 't Arrays not same length');
require(rates.length == symbols.length, 'r Arrays not same length');
for (uint256 i = 0; i < assets.length; i++) {
function initDeployment(InitDeploymentInput[] calldata inputParams) external onlyOwner {
for (uint256 i = 0; i < inputParams.length; i++) {
emit deployedContracts(
address(
new AToken(
LendingPool(pool),
assets[i],
treasuryAddress,
StringLib.concat('Aave interest bearing ', symbols[i]),
StringLib.concat('a', symbols[i]),
incentivesController
)
),
address(new AToken()),
address(
new DefaultReserveInterestRateStrategy(
LendingPoolAddressesProvider(addressesProvider),
rates[i][0],
rates[i][1],
rates[i][2],
rates[i][3],
rates[i][4],
rates[i][5]
inputParams[i].rates[0],
inputParams[i].rates[1],
inputParams[i].rates[2],
inputParams[i].rates[3],
inputParams[i].rates[4],
inputParams[i].rates[5]
)
)
);
}
}
function initReserve(
address[] calldata stables,
address[] calldata variables,
address[] calldata aTokens,
address[] calldata strategies,
uint8[] calldata reserveDecimals
) external onlyOwner {
require(variables.length == stables.length);
require(aTokens.length == stables.length);
require(strategies.length == stables.length);
require(reserveDecimals.length == stables.length);
for (uint256 i = 0; i < stables.length; i++) {
LendingPoolConfigurator(poolConfigurator).initReserve(
aTokens[i],
stables[i],
variables[i],
reserveDecimals[i],
strategies[i]
);
}
}
function configureReserves(
address[] calldata assets,
uint256[] calldata baseLTVs,
uint256[] calldata liquidationThresholds,
uint256[] calldata liquidationBonuses,
uint256[] calldata reserveFactors,
bool[] calldata stableBorrowingEnabled
) external onlyOwner {
require(baseLTVs.length == assets.length);
require(liquidationThresholds.length == assets.length);
require(liquidationBonuses.length == assets.length);
require(stableBorrowingEnabled.length == assets.length);
require(reserveFactors.length == assets.length);
function configureReserves(ConfigureReserveInput[] calldata inputParams) external onlyOwner {
LendingPoolConfigurator configurator = LendingPoolConfigurator(poolConfigurator);
for (uint256 i = 0; i < assets.length; i++) {
for (uint256 i = 0; i < inputParams.length; i++) {
configurator.configureReserveAsCollateral(
assets[i],
baseLTVs[i],
liquidationThresholds[i],
liquidationBonuses[i]
inputParams[i].asset,
inputParams[i].baseLTV,
inputParams[i].liquidationThreshold,
inputParams[i].liquidationBonus
);
configurator.enableBorrowingOnReserve(
assets[i],
stableBorrowingEnabled[i]
inputParams[i].asset,
inputParams[i].stableBorrowingEnabled
);
configurator.setReserveFactor(assets[i], reserveFactors[i]);
configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor);
}
}
}

View File

@ -18,34 +18,11 @@ contract StableAndVariableTokensHelper is Ownable {
addressesProvider = _addressesProvider;
}
function initDeployment(
address[] calldata tokens,
string[] calldata symbols,
address incentivesController
) external onlyOwner {
function initDeployment(address[] calldata tokens, string[] calldata symbols) external onlyOwner {
require(tokens.length == symbols.length, 'Arrays not same length');
require(pool != address(0), 'Pool can not be zero address');
for (uint256 i = 0; i < tokens.length; i++) {
emit deployedContracts(
address(
new StableDebtToken(
pool,
tokens[i],
StringLib.concat('Aave stable debt bearing ', symbols[i]),
StringLib.concat('stableDebt', symbols[i]),
incentivesController
)
),
address(
new VariableDebtToken(
pool,
tokens[i],
StringLib.concat('Aave variable debt bearing ', symbols[i]),
StringLib.concat('variableDebt', symbols[i]),
incentivesController
)
)
);
emit deployedContracts(address(new StableDebtToken()), address(new VariableDebtToken()));
}
}

View File

@ -3,8 +3,10 @@ pragma solidity 0.6.12;
import {IERC20} from '../dependencies/openzeppelin/contracts/IERC20.sol';
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
import {IInitializableAToken} from './IInitializableAToken.sol';
import {IAaveIncentivesController} from './IAaveIncentivesController.sol';
interface IAToken is IERC20, IScaledBalanceToken {
interface IAToken is IERC20, IScaledBalanceToken, IInitializableAToken {
/**
* @dev Emitted after the mint action
* @param from The address performing the mint
@ -80,9 +82,26 @@ interface IAToken is IERC20, IScaledBalanceToken {
/**
* @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer
* assets in borrow(), withdraw() and flashLoan()
* @param user The recipient of the aTokens
* @param user The recipient of the underlying
* @param amount The amount getting transferred
* @return The amount transferred
**/
function transferUnderlyingTo(address user, uint256 amount) external returns (uint256);
/**
* @dev Invoked to execute actions on the aToken side after a repayment.
* @param user The user executing the repayment
* @param amount The amount getting repaid
**/
function handleRepayment(address user, uint256 amount) external;
/**
* @dev Returns the address of the incentives controller contract
**/
function getIncentivesController() external view returns (IAaveIncentivesController);
/**
* @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
**/
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
}

View File

@ -3,9 +3,126 @@ pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
interface IAaveIncentivesController {
event RewardsAccrued(address indexed user, uint256 amount);
event RewardsClaimed(address indexed user, address indexed to, uint256 amount);
event RewardsClaimed(
address indexed user,
address indexed to,
address indexed claimer,
uint256 amount
);
event ClaimerSet(address indexed user, address indexed claimer);
/*
* @dev Returns the configuration of the distribution for a certain asset
* @param asset The address of the reference asset of the distribution
* @return The asset index, the emission per second and the last updated timestamp
**/
function getAssetData(address asset)
external
view
returns (
uint256,
uint256,
uint256
);
/**
* @dev Whitelists an address to claim the rewards on behalf of another address
* @param user The address of the user
* @param claimer The address of the claimer
*/
function setClaimer(address user, address claimer) external;
/**
* @dev Returns the whitelisted claimer for a certain address (0x0 if not set)
* @param user The address of the user
* @return The claimer address
*/
function getClaimer(address user) external view returns (address);
/**
* @dev Configure assets for a certain rewards emission
* @param assets The assets to incentivize
* @param emissionsPerSecond The emission for each asset
*/
function configureAssets(address[] calldata assets, uint256[] calldata emissionsPerSecond)
external;
/**
* @dev Called by the corresponding asset on any update that affects the rewards distribution
* @param asset The address of the user
* @param userBalance The balance of the user of the asset in the lending pool
* @param totalSupply The total supply of the asset in the lending pool
**/
function handleAction(
address user,
address asset,
uint256 userBalance,
uint256 totalSupply
) external;
/**
* @dev Returns the total of rewards of an user, already accrued + not yet accrued
* @param user The address of the user
* @return The rewards
**/
function getRewardsBalance(address[] calldata assets, address user)
external
view
returns (uint256);
/**
* @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards
* @param amount Amount of rewards to claim
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewards(
address[] calldata assets,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Claims reward for an user on behalf, on all the assets of the lending pool, accumulating the pending rewards. The caller must
* be whitelisted via "allowClaimOnBehalf" function by the RewardsAdmin role manager
* @param amount Amount of rewards to claim
* @param user Address to check and claim rewards
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewardsOnBehalf(
address[] calldata assets,
uint256 amount,
address user,
address to
) external returns (uint256);
/**
* @dev returns the unclaimed rewards of the user
* @param user the address of the user
* @return the unclaimed user rewards
*/
function getUserUnclaimedRewards(address user) external view returns (uint256);
/**
* @dev returns the unclaimed rewards of the user
* @param user the address of the user
* @param asset The asset to incentivize
* @return the user index for the asset
*/
function getUserAssetData(address user, address asset) external view returns (uint256);
/**
* @dev for backward compatibility with previous implementation of the Incentives controller
*/
function REWARD_TOKEN() external view returns (address);
/**
* @dev for backward compatibility with previous implementation of the Incentives controller
*/
function PRECISION() external view returns (uint8);
}

View File

@ -0,0 +1,55 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
import {ILendingPool} from './ILendingPool.sol';
import {IAaveIncentivesController} from './IAaveIncentivesController.sol';
/**
* @title IInitializableAToken
* @notice Interface for the initialize function on AToken
* @author Aave
**/
interface IInitializableAToken {
/**
* @dev Emitted when an aToken is initialized
* @param underlyingAsset The address of the underlying asset
* @param pool The address of the associated lending pool
* @param treasury The address of the treasury
* @param incentivesController The address of the incentives controller for this aToken
* @param aTokenDecimals the decimals of the underlying
* @param aTokenName the name of the aToken
* @param aTokenSymbol the symbol of the aToken
* @param params A set of encoded parameters for additional initialization
**/
event Initialized(
address indexed underlyingAsset,
address indexed pool,
address treasury,
address incentivesController,
uint8 aTokenDecimals,
string aTokenName,
string aTokenSymbol,
bytes params
);
/**
* @dev Initializes the aToken
* @param pool The address of the lending pool where this aToken will be used
* @param treasury The address of the Aave treasury, receiving the fees on this aToken
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @param incentivesController The smart contract managing potential incentives distribution
* @param aTokenDecimals The decimals of the aToken, same as the underlying asset's
* @param aTokenName The name of the aToken
* @param aTokenSymbol The symbol of the aToken
*/
function initialize(
ILendingPool pool,
address treasury,
address underlyingAsset,
IAaveIncentivesController incentivesController,
uint8 aTokenDecimals,
string calldata aTokenName,
string calldata aTokenSymbol,
bytes calldata params
) external;
}

View File

@ -0,0 +1,51 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
import {ILendingPool} from './ILendingPool.sol';
import {IAaveIncentivesController} from './IAaveIncentivesController.sol';
/**
* @title IInitializableDebtToken
* @notice Interface for the initialize function common between debt tokens
* @author Aave
**/
interface IInitializableDebtToken {
/**
* @dev Emitted when a debt token is initialized
* @param underlyingAsset The address of the underlying asset
* @param pool The address of the associated lending pool
* @param incentivesController The address of the incentives controller for this aToken
* @param debtTokenDecimals the decimals of the debt token
* @param debtTokenName the name of the debt token
* @param debtTokenSymbol the symbol of the debt token
* @param params A set of encoded parameters for additional initialization
**/
event Initialized(
address indexed underlyingAsset,
address indexed pool,
address incentivesController,
uint8 debtTokenDecimals,
string debtTokenName,
string debtTokenSymbol,
bytes params
);
/**
* @dev Initializes the debt token.
* @param pool The address of the lending pool where this aToken will be used
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @param incentivesController The smart contract managing potential incentives distribution
* @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's
* @param debtTokenName The name of the token
* @param debtTokenSymbol The symbol of the token
*/
function initialize(
ILendingPool pool,
address underlyingAsset,
IAaveIncentivesController incentivesController,
uint8 debtTokenDecimals,
string memory debtTokenName,
string memory debtTokenSymbol,
bytes calldata params
) external;
}

View File

@ -0,0 +1,179 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
interface ILendingPoolConfigurator {
struct InitReserveInput {
address aTokenImpl;
address stableDebtTokenImpl;
address variableDebtTokenImpl;
uint8 underlyingAssetDecimals;
address interestRateStrategyAddress;
address underlyingAsset;
address treasury;
address incentivesController;
string underlyingAssetName;
string aTokenName;
string aTokenSymbol;
string variableDebtTokenName;
string variableDebtTokenSymbol;
string stableDebtTokenName;
string stableDebtTokenSymbol;
bytes params;
}
struct UpdateATokenInput {
address asset;
address treasury;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
struct UpdateDebtTokenInput {
address asset;
address incentivesController;
string name;
string symbol;
address implementation;
bytes params;
}
/**
* @dev Emitted when a reserve is initialized.
* @param asset The address of the underlying asset of the reserve
* @param aToken The address of the associated aToken contract
* @param stableDebtToken The address of the associated stable rate debt token
* @param variableDebtToken The address of the associated variable rate debt token
* @param interestRateStrategyAddress The address of the interest rate strategy for the reserve
**/
event ReserveInitialized(
address indexed asset,
address indexed aToken,
address stableDebtToken,
address variableDebtToken,
address interestRateStrategyAddress
);
/**
* @dev Emitted when borrowing is enabled on a reserve
* @param asset The address of the underlying asset of the reserve
* @param stableRateEnabled True if stable rate borrowing is enabled, false otherwise
**/
event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled);
/**
* @dev Emitted when borrowing is disabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event BorrowingDisabledOnReserve(address indexed asset);
/**
* @dev Emitted when the collateralization risk parameters for the specified asset are updated.
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
**/
event CollateralConfigurationChanged(
address indexed asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
);
/**
* @dev Emitted when stable rate borrowing is enabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event StableRateEnabledOnReserve(address indexed asset);
/**
* @dev Emitted when stable rate borrowing is disabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event StableRateDisabledOnReserve(address indexed asset);
/**
* @dev Emitted when a reserve is activated
* @param asset The address of the underlying asset of the reserve
**/
event ReserveActivated(address indexed asset);
/**
* @dev Emitted when a reserve is deactivated
* @param asset The address of the underlying asset of the reserve
**/
event ReserveDeactivated(address indexed asset);
/**
* @dev Emitted when a reserve is frozen
* @param asset The address of the underlying asset of the reserve
**/
event ReserveFrozen(address indexed asset);
/**
* @dev Emitted when a reserve is unfrozen
* @param asset The address of the underlying asset of the reserve
**/
event ReserveUnfrozen(address indexed asset);
/**
* @dev Emitted when a reserve factor is updated
* @param asset The address of the underlying asset of the reserve
* @param factor The new reserve factor
**/
event ReserveFactorChanged(address indexed asset, uint256 factor);
/**
* @dev Emitted when the reserve decimals are updated
* @param asset The address of the underlying asset of the reserve
* @param decimals The new decimals
**/
event ReserveDecimalsChanged(address indexed asset, uint256 decimals);
/**
* @dev Emitted when a reserve interest strategy contract is updated
* @param asset The address of the underlying asset of the reserve
* @param strategy The new address of the interest strategy contract
**/
event ReserveInterestRateStrategyChanged(address indexed asset, address strategy);
/**
* @dev Emitted when an aToken implementation is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The aToken proxy address
* @param implementation The new aToken implementation
**/
event ATokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a stable debt token is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The stable debt token proxy address
* @param implementation The new aToken implementation
**/
event StableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a variable debt token is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The variable debt token proxy address
* @param implementation The new aToken implementation
**/
event VariableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
}

View File

@ -13,7 +13,25 @@ interface IReserveInterestRateStrategy {
function calculateInterestRates(
address reserve,
uint256 utilizationRate,
uint256 availableLiquidity,
uint256 totalStableDebt,
uint256 totalVariableDebt,
uint256 averageStableBorrowRate,
uint256 reserveFactor
)
external
view
returns (
uint256,
uint256,
uint256
);
function calculateInterestRates(
address reserve,
address aToken,
uint256 liquidityAdded,
uint256 liquidityTaken,
uint256 totalStableDebt,
uint256 totalVariableDebt,
uint256 averageStableBorrowRate,

View File

@ -1,6 +1,9 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity 0.6.12;
import {IInitializableDebtToken} from './IInitializableDebtToken.sol';
import {IAaveIncentivesController} from './IAaveIncentivesController.sol';
/**
* @title IStableDebtToken
* @notice Defines the interface for the stable debt token
@ -8,7 +11,7 @@ pragma solidity 0.6.12;
* @author Aave
**/
interface IStableDebtToken {
interface IStableDebtToken is IInitializableDebtToken {
/**
* @dev Emitted when new stable debt is minted
* @param user The address of the user who triggered the minting
@ -122,4 +125,9 @@ interface IStableDebtToken {
* @return The debt balance of the user since the last burn/mint action
**/
function principalBalanceOf(address user) external view returns (uint256);
/**
* @dev Returns the address of the incentives controller contract
**/
function getIncentivesController() external view returns (IAaveIncentivesController);
}

View File

@ -1,14 +0,0 @@
// SPDX-License-Identifier: agpl-3.0
pragma solidity ^0.6.12;
/**
* @title ITokenConfiguration
* @author Aave
* @dev Common interface between aTokens and debt tokens to fetch the
* token configuration
**/
interface ITokenConfiguration {
function UNDERLYING_ASSET_ADDRESS() external view returns (address);
function POOL() external view returns (address);
}

View File

@ -11,14 +11,20 @@ interface IUniswapV2Router02 {
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint deadline
uint256 deadline
) external returns (uint256[] memory amounts);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsOut(uint256 amountIn, address[] calldata path)
external
view
returns (uint256[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint256 amountOut, address[] calldata path)
external
view
returns (uint256[] memory amounts);
}

View File

@ -2,13 +2,15 @@
pragma solidity 0.6.12;
import {IScaledBalanceToken} from './IScaledBalanceToken.sol';
import {IInitializableDebtToken} from './IInitializableDebtToken.sol';
import {IAaveIncentivesController} from './IAaveIncentivesController.sol';
/**
* @title IVariableDebtToken
* @author Aave
* @notice Defines the basic interface for a variable debt token.
**/
interface IVariableDebtToken is IScaledBalanceToken {
interface IVariableDebtToken is IScaledBalanceToken, IInitializableDebtToken {
/**
* @dev Emitted after the mint action
* @param from The address performing the mint
@ -52,4 +54,9 @@ interface IVariableDebtToken is IScaledBalanceToken {
uint256 amount,
uint256 index
) external;
/**
* @dev Returns the address of the incentives controller contract
**/
function getIncentivesController() external view returns (IAaveIncentivesController);
}

View File

@ -80,7 +80,7 @@ contract AaveOracle is IPriceOracleGetter, Ownable {
/// @notice Gets an asset price by address
/// @param asset The asset address
function getAssetPrice(address asset) public override view returns (uint256) {
function getAssetPrice(address asset) public view override returns (uint256) {
IChainlinkAggregator source = assetsSources[asset];
if (asset == WETH) {

View File

@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2;
import {IERC20Detailed} from '../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {ILendingPoolAddressesProvider} from '../interfaces/ILendingPoolAddressesProvider.sol';
import {IAaveIncentivesController} from '../interfaces/IAaveIncentivesController.sol';
import {IUiPoolDataProvider} from './interfaces/IUiPoolDataProvider.sol';
import {ILendingPool} from '../interfaces/ILendingPool.sol';
import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol';
@ -24,6 +25,13 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
using UserConfiguration for DataTypes.UserConfigurationMap;
address public constant MOCK_USD_ADDRESS = 0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96;
IAaveIncentivesController public immutable incentivesController;
IPriceOracleGetter public immutable oracle;
constructor(IAaveIncentivesController _incentivesController, IPriceOracleGetter _oracle) public {
incentivesController = _incentivesController;
oracle = _oracle;
}
function getInterestRateStrategySlopes(DefaultReserveInterestRateStrategy interestRateStrategy)
internal
@ -50,11 +58,11 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
returns (
AggregatedReserveData[] memory,
UserReserveData[] memory,
uint256,
uint256
)
{
ILendingPool lendingPool = ILendingPool(provider.getLendingPool());
IPriceOracleGetter oracle = IPriceOracleGetter(provider.getPriceOracle());
address[] memory reserves = lendingPool.getReservesList();
DataTypes.UserConfigurationMap memory userConfig = lendingPool.getUserConfiguration(user);
@ -122,7 +130,43 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
DefaultReserveInterestRateStrategy(reserveData.interestRateStrategyAddress)
);
// incentives
if (address(0) != address(incentivesController)) {
(
reserveData.aEmissionPerSecond,
reserveData.aIncentivesLastUpdateTimestamp,
reserveData.aTokenIncentivesIndex
) = incentivesController.getAssetData(reserveData.aTokenAddress);
(
reserveData.sEmissionPerSecond,
reserveData.sIncentivesLastUpdateTimestamp,
reserveData.sTokenIncentivesIndex
) = incentivesController.getAssetData(reserveData.stableDebtTokenAddress);
(
reserveData.vEmissionPerSecond,
reserveData.vIncentivesLastUpdateTimestamp,
reserveData.vTokenIncentivesIndex
) = incentivesController.getAssetData(reserveData.variableDebtTokenAddress);
}
if (user != address(0)) {
// incentives
if (address(0) != address(incentivesController)) {
userReservesData[i].aTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
reserveData.aTokenAddress
);
userReservesData[i].vTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
reserveData.variableDebtTokenAddress
);
userReservesData[i].sTokenincentivesUserIndex = incentivesController.getUserAssetData(
user,
reserveData.stableDebtTokenAddress
);
}
// user reserve data
userReservesData[i].underlyingAsset = reserveData.underlyingAsset;
userReservesData[i].scaledATokenBalance = IAToken(reserveData.aTokenAddress)
@ -155,6 +199,12 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
}
}
}
return (reservesData, userReservesData, oracle.getAssetPrice(MOCK_USD_ADDRESS));
return (
reservesData,
userReservesData,
oracle.getAssetPrice(MOCK_USD_ADDRESS),
incentivesController.getUserUnclaimedRewards(user)
);
}
}

View File

@ -18,39 +18,47 @@ contract WETHGateway is IWETHGateway, Ownable {
using UserConfiguration for DataTypes.UserConfigurationMap;
IWETH internal immutable WETH;
ILendingPool internal immutable POOL;
IAToken internal immutable aWETH;
/**
* @dev Sets the WETH address and the LendingPoolAddressesProvider address. Infinite approves lending pool.
* @param weth Address of the Wrapped Ether contract
* @param pool Address of the LendingPool contract
**/
constructor(address weth, address pool) public {
ILendingPool poolInstance = ILendingPool(pool);
constructor(address weth) public {
WETH = IWETH(weth);
POOL = poolInstance;
aWETH = IAToken(poolInstance.getReserveData(weth).aTokenAddress);
IWETH(weth).approve(pool, uint256(-1));
}
function authorizeLendingPool(address lendingPool) external onlyOwner {
WETH.approve(lendingPool, uint256(-1));
}
/**
* @dev deposits WETH into the reserve, using native ETH. A corresponding amount of the overlying asset (aTokens)
* is minted.
* @param lendingPool address of the targeted underlying lending pool
* @param onBehalfOf address of the user who will receive the aTokens representing the deposit
* @param referralCode integrators are assigned a referral code and can potentially receive rewards.
**/
function depositETH(address onBehalfOf, uint16 referralCode) external payable override {
function depositETH(
address lendingPool,
address onBehalfOf,
uint16 referralCode
) external payable override {
WETH.deposit{value: msg.value}();
POOL.deposit(address(WETH), msg.value, onBehalfOf, referralCode);
ILendingPool(lendingPool).deposit(address(WETH), msg.value, onBehalfOf, referralCode);
}
/**
* @dev withdraws the WETH _reserves of msg.sender.
* @param lendingPool address of the targeted underlying lending pool
* @param amount amount of aWETH to withdraw and receive native ETH
* @param to address of the user who will receive native ETH
*/
function withdrawETH(uint256 amount, address to) external override {
function withdrawETH(
address lendingPool,
uint256 amount,
address to
) external override {
IAToken aWETH = IAToken(ILendingPool(lendingPool).getReserveData(address(WETH)).aTokenAddress);
uint256 userBalance = aWETH.balanceOf(msg.sender);
uint256 amountToWithdraw = amount;
@ -59,24 +67,29 @@ contract WETHGateway is IWETHGateway, Ownable {
amountToWithdraw = userBalance;
}
aWETH.transferFrom(msg.sender, address(this), amountToWithdraw);
POOL.withdraw(address(WETH), amountToWithdraw, address(this));
ILendingPool(lendingPool).withdraw(address(WETH), amountToWithdraw, address(this));
WETH.withdraw(amountToWithdraw);
_safeTransferETH(to, amountToWithdraw);
}
/**
* @dev repays a borrow on the WETH reserve, for the specified amount (or for the whole amount, if uint256(-1) is specified).
* @param lendingPool address of the targeted underlying lending pool
* @param amount the amount to repay, or uint256(-1) if the user wants to repay everything
* @param rateMode the rate mode to repay
* @param onBehalfOf the address for which msg.sender is repaying
*/
function repayETH(
address lendingPool,
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external payable override {
(uint256 stableDebt, uint256 variableDebt) =
Helpers.getUserCurrentDebtMemory(onBehalfOf, POOL.getReserveData(address(WETH)));
Helpers.getUserCurrentDebtMemory(
onBehalfOf,
ILendingPool(lendingPool).getReserveData(address(WETH))
);
uint256 paybackAmount =
DataTypes.InterestRateMode(rateMode) == DataTypes.InterestRateMode.STABLE
@ -88,7 +101,7 @@ contract WETHGateway is IWETHGateway, Ownable {
}
require(msg.value >= paybackAmount, 'msg.value is less than repayment amount');
WETH.deposit{value: paybackAmount}();
POOL.repay(address(WETH), msg.value, rateMode, onBehalfOf);
ILendingPool(lendingPool).repay(address(WETH), msg.value, rateMode, onBehalfOf);
// refund remaining dust eth
if (msg.value > paybackAmount) _safeTransferETH(msg.sender, msg.value - paybackAmount);
@ -96,16 +109,24 @@ contract WETHGateway is IWETHGateway, Ownable {
/**
* @dev borrow WETH, unwraps to ETH and send both the ETH and DebtTokens to msg.sender, via `approveDelegation` and onBehalf argument in `LendingPool.borrow`.
* @param lendingPool address of the targeted underlying lending pool
* @param amount the amount of ETH to borrow
* @param interesRateMode the interest rate mode
* @param referralCode integrators are assigned a referral code and can potentially receive rewards
*/
function borrowETH(
address lendingPool,
uint256 amount,
uint256 interesRateMode,
uint16 referralCode
) external override {
POOL.borrow(address(WETH), amount, interesRateMode, referralCode, msg.sender);
ILendingPool(lendingPool).borrow(
address(WETH),
amount,
interesRateMode,
referralCode,
msg.sender
);
WETH.withdraw(amount);
_safeTransferETH(msg.sender, amount);
}
@ -152,20 +173,6 @@ contract WETHGateway is IWETHGateway, Ownable {
return address(WETH);
}
/**
* @dev Get aWETH address used by WETHGateway
*/
function getAWETHAddress() external view returns (address) {
return address(aWETH);
}
/**
* @dev Get LendingPool address used by WETHGateway
*/
function getLendingPoolAddress() external view returns (address) {
return address(POOL);
}
/**
* @dev Only WETH contract is allowed to transfer ETH here. Prevent other addresses to send Ether to this contract.
*/

View File

@ -93,7 +93,8 @@ contract WalletBalanceProvider {
uint256[] memory balances = new uint256[](reservesWithEth.length);
for (uint256 j = 0; j < reserves.length; j++) {
DataTypes.ReserveConfigurationMap memory configuration = pool.getConfiguration(reservesWithEth[j]);
DataTypes.ReserveConfigurationMap memory configuration =
pool.getConfiguration(reservesWithEth[j]);
(bool isActive, , , ) = configuration.getFlagsMemory();

View File

@ -3,6 +3,7 @@ pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
interface IUiPoolDataProvider {
struct AggregatedReserveData {
@ -41,12 +42,17 @@ interface IUiPoolDataProvider {
uint256 variableRateSlope2;
uint256 stableRateSlope1;
uint256 stableRateSlope2;
// incentives
uint256 aEmissionPerSecond;
uint256 vEmissionPerSecond;
uint256 sEmissionPerSecond;
uint256 aIncentivesLastUpdateTimestamp;
uint256 vIncentivesLastUpdateTimestamp;
uint256 sIncentivesLastUpdateTimestamp;
uint256 aTokenIncentivesIndex;
uint256 vTokenIncentivesIndex;
uint256 sTokenIncentivesIndex;
}
//
// struct ReserveData {
// uint256 averageStableBorrowRate;
// uint256 totalLiquidity;
// }
struct UserReserveData {
address underlyingAsset;
@ -56,38 +62,19 @@ interface IUiPoolDataProvider {
uint256 scaledVariableDebt;
uint256 principalStableDebt;
uint256 stableBorrowLastUpdateTimestamp;
// incentives
uint256 aTokenincentivesUserIndex;
uint256 vTokenincentivesUserIndex;
uint256 sTokenincentivesUserIndex;
}
//
// struct ATokenSupplyData {
// string name;
// string symbol;
// uint8 decimals;
// uint256 totalSupply;
// address aTokenAddress;
// }
function getReservesData(ILendingPoolAddressesProvider provider, address user)
external
view
returns (
AggregatedReserveData[] memory,
UserReserveData[] memory,
uint256,
uint256
);
// function getUserReservesData(ILendingPoolAddressesProvider provider, address user)
// external
// view
// returns (UserReserveData[] memory);
//
// function getAllATokenSupply(ILendingPoolAddressesProvider provider)
// external
// view
// returns (ATokenSupplyData[] memory);
//
// function getATokenSupply(address[] calldata aTokens)
// external
// view
// returns (ATokenSupplyData[] memory);
}

View File

@ -2,17 +2,27 @@
pragma solidity 0.6.12;
interface IWETHGateway {
function depositETH(address onBehalfOf, uint16 referralCode) external payable;
function depositETH(
address lendingPool,
address onBehalfOf,
uint16 referralCode
) external payable;
function withdrawETH(uint256 amount, address onBehalfOf) external;
function withdrawETH(
address lendingPool,
uint256 amount,
address onBehalfOf
) external;
function repayETH(
address lendingPool,
uint256 amount,
uint256 rateMode,
address onBehalfOf
) external payable;
function borrowETH(
address lendingPool,
uint256 amount,
uint256 interesRateMode,
uint16 referralCode

View File

@ -68,9 +68,8 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
'Invalid balance for the contract'
);
uint256 amountToReturn = (_amountToApprove != 0)
? _amountToApprove
: amounts[i].add(premiums[i]);
uint256 amountToReturn =
(_amountToApprove != 0) ? _amountToApprove : amounts[i].add(premiums[i]);
//execution does not fail - mint tokens and return them to the _destination
token.mint(premiums[i]);

View File

@ -8,7 +8,7 @@ contract LendingRateOracle is ILendingRateOracle, Ownable {
mapping(address => uint256) borrowRates;
mapping(address => uint256) liquidityRates;
function getMarketBorrowRate(address _asset) external override view returns (uint256) {
function getMarketBorrowRate(address _asset) external view override returns (uint256) {
return borrowRates[_asset];
}

View File

@ -10,7 +10,7 @@ contract PriceOracle is IPriceOracle {
event AssetPriceUpdated(address _asset, uint256 _price, uint256 timestamp);
event EthPriceUpdated(uint256 _price, uint256 timestamp);
function getAssetPrice(address _asset) external override view returns (uint256) {
function getAssetPrice(address _asset) external view override returns (uint256) {
return prices[_asset];
}

View File

@ -2,39 +2,11 @@
pragma solidity 0.6.12;
import {AToken} from '../../protocol/tokenization/AToken.sol';
import {LendingPool} from '../../protocol/lendingpool/LendingPool.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
contract MockAToken is AToken {
constructor(
LendingPool pool,
address underlyingAssetAddress,
address reserveTreasury,
string memory tokenName,
string memory tokenSymbol,
address incentivesController
)
public
AToken(
pool,
underlyingAssetAddress,
reserveTreasury,
tokenName,
tokenSymbol,
incentivesController
)
{}
function getRevision() internal pure override returns (uint256) {
return 0x2;
}
function initialize(
uint8 _underlyingAssetDecimals,
string calldata _tokenName,
string calldata _tokenSymbol
) external virtual override initializer {
_setName(_tokenName);
_setSymbol(_tokenSymbol);
_setDecimals(_underlyingAssetDecimals);
}
}

View File

@ -4,17 +4,6 @@ pragma solidity 0.6.12;
import {StableDebtToken} from '../../protocol/tokenization/StableDebtToken.sol';
contract MockStableDebtToken is StableDebtToken {
constructor(
address _pool,
address _underlyingAssetAddress,
string memory _tokenName,
string memory _tokenSymbol,
address incentivesController
)
public
StableDebtToken(_pool, _underlyingAssetAddress, _tokenName, _tokenSymbol, incentivesController)
{}
function getRevision() internal pure override returns (uint256) {
return 0x2;
}

View File

@ -4,23 +4,6 @@ pragma solidity 0.6.12;
import {VariableDebtToken} from '../../protocol/tokenization/VariableDebtToken.sol';
contract MockVariableDebtToken is VariableDebtToken {
constructor(
address _pool,
address _underlyingAssetAddress,
string memory _tokenName,
string memory _tokenSymbol,
address incentivesController
)
public
VariableDebtToken(
_pool,
_underlyingAssetAddress,
_tokenName,
_tokenSymbol,
incentivesController
)
{}
function getRevision() internal pure override returns (uint256) {
return 0x2;
}

View File

@ -7,6 +7,7 @@ import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingRateOracle} from '../../interfaces/ILendingRateOracle.sol';
import {IERC20} from '../../dependencies/openzeppelin/contracts/IERC20.sol';
/**
* @title DefaultReserveInterestRateStrategy contract
@ -96,6 +97,51 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
return _baseVariableBorrowRate.add(_variableRateSlope1).add(_variableRateSlope2);
}
/**
* @dev Calculates the interest rates depending on the reserve's state and configurations
* @param reserve The address of the reserve
* @param liquidityAdded The liquidity added during the operation
* @param liquidityTaken The liquidity taken during the operation
* @param totalStableDebt The total borrowed from the reserve a stable rate
* @param totalVariableDebt The total borrowed from the reserve at a variable rate
* @param averageStableBorrowRate The weighted average of all the stable rate loans
* @param reserveFactor The reserve portion of the interest that goes to the treasury of the market
* @return The liquidity rate, the stable borrow rate and the variable borrow rate
**/
function calculateInterestRates(
address reserve,
address aToken,
uint256 liquidityAdded,
uint256 liquidityTaken,
uint256 totalStableDebt,
uint256 totalVariableDebt,
uint256 averageStableBorrowRate,
uint256 reserveFactor
)
external
view
override
returns (
uint256,
uint256,
uint256
)
{
uint256 availableLiquidity = IERC20(reserve).balanceOf(aToken);
//avoid stack too deep
availableLiquidity = availableLiquidity.add(liquidityAdded).sub(liquidityTaken);
return
calculateInterestRates(
reserve,
availableLiquidity,
totalStableDebt,
totalVariableDebt,
averageStableBorrowRate,
reserveFactor
);
}
struct CalcInterestRatesLocalVars {
uint256 totalDebt;
uint256 currentVariableBorrowRate;
@ -105,9 +151,11 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
}
/**
* @dev Calculates the interest rates depending on the reserve's state and configurations
* @dev Calculates the interest rates depending on the reserve's state and configurations.
* NOTE This function is kept for compatibility with the previous DefaultInterestRateStrategy interface.
* New protocol implementation uses the new calculateInterestRates() interface
* @param reserve The address of the reserve
* @param availableLiquidity The liquidity available in the reserve
* @param availableLiquidity The liquidity available in the corresponding aToken
* @param totalStableDebt The total borrowed from the reserve a stable rate
* @param totalVariableDebt The total borrowed from the reserve at a variable rate
* @param averageStableBorrowRate The weighted average of all the stable rate loans
@ -122,7 +170,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
uint256 averageStableBorrowRate,
uint256 reserveFactor
)
external
public
view
override
returns (
@ -138,17 +186,16 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
vars.currentStableBorrowRate = 0;
vars.currentLiquidityRate = 0;
uint256 utilizationRate =
vars.totalDebt == 0
? 0
: vars.totalDebt.rayDiv(availableLiquidity.add(vars.totalDebt));
vars.utilizationRate = vars.totalDebt == 0
? 0
: vars.totalDebt.rayDiv(availableLiquidity.add(vars.totalDebt));
vars.currentStableBorrowRate = ILendingRateOracle(addressesProvider.getLendingRateOracle())
.getMarketBorrowRate(reserve);
if (utilizationRate > OPTIMAL_UTILIZATION_RATE) {
if (vars.utilizationRate > OPTIMAL_UTILIZATION_RATE) {
uint256 excessUtilizationRateRatio =
utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(EXCESS_UTILIZATION_RATE);
vars.utilizationRate.sub(OPTIMAL_UTILIZATION_RATE).rayDiv(EXCESS_UTILIZATION_RATE);
vars.currentStableBorrowRate = vars.currentStableBorrowRate.add(_stableRateSlope1).add(
_stableRateSlope2.rayMul(excessUtilizationRateRatio)
@ -159,10 +206,10 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
);
} else {
vars.currentStableBorrowRate = vars.currentStableBorrowRate.add(
_stableRateSlope1.rayMul(utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
_stableRateSlope1.rayMul(vars.utilizationRate.rayDiv(OPTIMAL_UTILIZATION_RATE))
);
vars.currentVariableBorrowRate = _baseVariableBorrowRate.add(
utilizationRate.rayMul(_variableRateSlope1).rayDiv(OPTIMAL_UTILIZATION_RATE)
vars.utilizationRate.rayMul(_variableRateSlope1).rayDiv(OPTIMAL_UTILIZATION_RATE)
);
}
@ -173,7 +220,7 @@ contract DefaultReserveInterestRateStrategy is IReserveInterestRateStrategy {
.currentVariableBorrowRate,
averageStableBorrowRate
)
.rayMul(utilizationRate)
.rayMul(vars.utilizationRate)
.percentMul(PercentageMath.PERCENTAGE_FACTOR.sub(reserveFactor));
return (

View File

@ -49,10 +49,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
using PercentageMath for uint256;
using SafeERC20 for IERC20;
//main configuration parameters
uint256 public constant MAX_STABLE_RATE_BORROW_SIZE_PERCENT = 2500;
uint256 public constant FLASHLOAN_PREMIUM_TOTAL = 9;
uint256 public constant MAX_NUMBER_RESERVES = 128;
uint256 public constant LENDINGPOOL_REVISION = 0x2;
modifier whenNotPaused() {
@ -89,6 +85,9 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
**/
function initialize(ILendingPoolAddressesProvider provider) public initializer {
_addressesProvider = provider;
_maxStableRateBorrowSizePercent = 2500;
_flashLoanPremiumTotal = 9;
_maxNumberOfReserves = 128;
}
/**
@ -144,7 +143,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
address asset,
uint256 amount,
address to
) external override whenNotPaused returns (uint256) {
) external override whenNotPaused returns (uint256) {
DataTypes.ReserveData storage reserve = _reserves[asset];
address aToken = reserve.aTokenAddress;
@ -283,6 +282,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
IERC20(asset).safeTransferFrom(msg.sender, aToken, paybackAmount);
IAToken(aToken).handleRepayment(msg.sender, paybackAmount);
emit Repay(asset, onBehalfOf, msg.sender, paybackAmount);
return paybackAmount;
@ -442,6 +443,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
receiveAToken
)
);
require(success, Errors.LP_LIQUIDATION_CALL_FAILED);
(uint256 returnCode, string memory returnMessage) = abi.decode(result, (uint256, string));
@ -499,7 +501,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
for (vars.i = 0; vars.i < assets.length; vars.i++) {
aTokenAddresses[vars.i] = _reserves[assets[vars.i]].aTokenAddress;
premiums[vars.i] = amounts[vars.i].mul(FLASHLOAN_PREMIUM_TOTAL).div(10000);
premiums[vars.i] = amounts[vars.i].mul(_flashLoanPremiumTotal).div(10000);
IAToken(aTokenAddresses[vars.i]).transferUnderlyingTo(receiverAddress, amounts[vars.i]);
}
@ -703,6 +705,27 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
return _addressesProvider;
}
/**
* @dev Returns the percentage of available liquidity that can be borrowed at once at stable rate
*/
function MAX_STABLE_RATE_BORROW_SIZE_PERCENT() public view returns (uint256) {
return _maxStableRateBorrowSizePercent;
}
/**
* @dev Returns the fee on flash loans
*/
function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) {
return _flashLoanPremiumTotal;
}
/**
* @dev Returns the maximum number of reserves supported to be listed in this LendingPool
*/
function MAX_NUMBER_RESERVES() public view returns (uint256) {
return _maxNumberOfReserves;
}
/**
* @dev Validates and finalizes an aToken transfer
* - Only callable by the overlying aToken of the `asset`
@ -847,7 +870,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
vars.amount,
amountInETH,
vars.interestRateMode,
MAX_STABLE_RATE_BORROW_SIZE_PERCENT,
_maxStableRateBorrowSizePercent,
_reserves,
userConfig,
_reservesList,
@ -909,7 +932,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
function _addReserveToList(address asset) internal {
uint256 reservesCount = _reservesCount;
require(reservesCount < MAX_NUMBER_RESERVES, Errors.LP_NO_MORE_RESERVES_ALLOWED);
require(reservesCount < _maxNumberOfReserves, Errors.LP_NO_MORE_RESERVES_ALLOWED);
bool reserveAlreadyAdded = _reserves[asset].id != 0 || _reservesList[0] == asset;

View File

@ -10,11 +10,14 @@ import {
import {ReserveConfiguration} from '../libraries/configuration/ReserveConfiguration.sol';
import {ILendingPoolAddressesProvider} from '../../interfaces/ILendingPoolAddressesProvider.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {ITokenConfiguration} from '../../interfaces/ITokenConfiguration.sol';
import {IERC20Detailed} from '../../dependencies/openzeppelin/contracts/IERC20Detailed.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {PercentageMath} from '../libraries/math/PercentageMath.sol';
import {DataTypes} from '../libraries/types/DataTypes.sol';
import {IInitializableDebtToken} from '../../interfaces/IInitializableDebtToken.sol';
import {IInitializableAToken} from '../../interfaces/IInitializableAToken.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
import {ILendingPoolConfigurator} from '../../interfaces/ILendingPoolConfigurator.sol';
/**
* @title LendingPoolConfigurator contract
@ -22,147 +25,11 @@ import {DataTypes} from '../libraries/types/DataTypes.sol';
* @dev Implements the configuration methods for the Aave protocol
**/
contract LendingPoolConfigurator is VersionedInitializable {
contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigurator {
using SafeMath for uint256;
using PercentageMath for uint256;
using ReserveConfiguration for DataTypes.ReserveConfigurationMap;
/**
* @dev Emitted when a reserve is initialized.
* @param asset The address of the underlying asset of the reserve
* @param aToken The address of the associated aToken contract
* @param stableDebtToken The address of the associated stable rate debt token
* @param variableDebtToken The address of the associated variable rate debt token
* @param interestRateStrategyAddress The address of the interest rate strategy for the reserve
**/
event ReserveInitialized(
address indexed asset,
address indexed aToken,
address stableDebtToken,
address variableDebtToken,
address interestRateStrategyAddress
);
/**
* @dev Emitted when borrowing is enabled on a reserve
* @param asset The address of the underlying asset of the reserve
* @param stableRateEnabled True if stable rate borrowing is enabled, false otherwise
**/
event BorrowingEnabledOnReserve(address indexed asset, bool stableRateEnabled);
/**
* @dev Emitted when borrowing is disabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event BorrowingDisabledOnReserve(address indexed asset);
/**
* @dev Emitted when the collateralization risk parameters for the specified asset are updated.
* @param asset The address of the underlying asset of the reserve
* @param ltv The loan to value of the asset when used as collateral
* @param liquidationThreshold The threshold at which loans using this asset as collateral will be considered undercollateralized
* @param liquidationBonus The bonus liquidators receive to liquidate this asset
**/
event CollateralConfigurationChanged(
address indexed asset,
uint256 ltv,
uint256 liquidationThreshold,
uint256 liquidationBonus
);
/**
* @dev Emitted when stable rate borrowing is enabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event StableRateEnabledOnReserve(address indexed asset);
/**
* @dev Emitted when stable rate borrowing is disabled on a reserve
* @param asset The address of the underlying asset of the reserve
**/
event StableRateDisabledOnReserve(address indexed asset);
/**
* @dev Emitted when a reserve is activated
* @param asset The address of the underlying asset of the reserve
**/
event ReserveActivated(address indexed asset);
/**
* @dev Emitted when a reserve is deactivated
* @param asset The address of the underlying asset of the reserve
**/
event ReserveDeactivated(address indexed asset);
/**
* @dev Emitted when a reserve is frozen
* @param asset The address of the underlying asset of the reserve
**/
event ReserveFrozen(address indexed asset);
/**
* @dev Emitted when a reserve is unfrozen
* @param asset The address of the underlying asset of the reserve
**/
event ReserveUnfrozen(address indexed asset);
/**
* @dev Emitted when a reserve factor is updated
* @param asset The address of the underlying asset of the reserve
* @param factor The new reserve factor
**/
event ReserveFactorChanged(address indexed asset, uint256 factor);
/**
* @dev Emitted when the reserve decimals are updated
* @param asset The address of the underlying asset of the reserve
* @param decimals The new decimals
**/
event ReserveDecimalsChanged(address indexed asset, uint256 decimals);
/**
* @dev Emitted when a reserve interest strategy contract is updated
* @param asset The address of the underlying asset of the reserve
* @param strategy The new address of the interest strategy contract
**/
event ReserveInterestRateStrategyChanged(address indexed asset, address strategy);
/**
* @dev Emitted when an aToken implementation is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The aToken proxy address
* @param implementation The new aToken implementation
**/
event ATokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a stable debt token is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The stable debt token proxy address
* @param implementation The new aToken implementation
**/
event StableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
/**
* @dev Emitted when the implementation of a variable debt token is upgraded
* @param asset The address of the underlying asset of the reserve
* @param proxy The variable debt token proxy address
* @param implementation The new aToken implementation
**/
event VariableDebtTokenUpgraded(
address indexed asset,
address indexed proxy,
address indexed implementation
);
ILendingPoolAddressesProvider internal addressesProvider;
ILendingPool internal pool;
@ -191,114 +58,189 @@ contract LendingPoolConfigurator is VersionedInitializable {
}
/**
* @dev Initializes a reserve
* @param aTokenImpl The address of the aToken contract implementation
* @param stableDebtTokenImpl The address of the stable debt token contract
* @param variableDebtTokenImpl The address of the variable debt token contract
* @param underlyingAssetDecimals The decimals of the reserve underlying asset
* @param interestRateStrategyAddress The address of the interest rate strategy contract for this reserve
* @dev Initializes reserves in batch
**/
function initReserve(
address aTokenImpl,
address stableDebtTokenImpl,
address variableDebtTokenImpl,
uint8 underlyingAssetDecimals,
address interestRateStrategyAddress
) public onlyPoolAdmin {
address asset = ITokenConfiguration(aTokenImpl).UNDERLYING_ASSET_ADDRESS();
function batchInitReserve(InitReserveInput[] calldata input) external onlyPoolAdmin {
ILendingPool cachedPool = pool;
for (uint256 i = 0; i < input.length; i++) {
_initReserve(cachedPool, input[i]);
}
}
require(
address(pool) == ITokenConfiguration(aTokenImpl).POOL(),
Errors.LPC_INVALID_ATOKEN_POOL_ADDRESS
);
require(
address(pool) == ITokenConfiguration(stableDebtTokenImpl).POOL(),
Errors.LPC_INVALID_STABLE_DEBT_TOKEN_POOL_ADDRESS
);
require(
address(pool) == ITokenConfiguration(variableDebtTokenImpl).POOL(),
Errors.LPC_INVALID_VARIABLE_DEBT_TOKEN_POOL_ADDRESS
);
require(
asset == ITokenConfiguration(stableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(),
Errors.LPC_INVALID_STABLE_DEBT_TOKEN_UNDERLYING_ADDRESS
);
require(
asset == ITokenConfiguration(variableDebtTokenImpl).UNDERLYING_ASSET_ADDRESS(),
Errors.LPC_INVALID_VARIABLE_DEBT_TOKEN_UNDERLYING_ADDRESS
);
address aTokenProxyAddress = _initTokenWithProxy(aTokenImpl, underlyingAssetDecimals);
function _initReserve(ILendingPool pool, InitReserveInput calldata input) internal {
address aTokenProxyAddress =
_initTokenWithProxy(
input.aTokenImpl,
abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
pool,
input.treasury,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.aTokenName,
input.aTokenSymbol,
input.params
)
);
address stableDebtTokenProxyAddress =
_initTokenWithProxy(stableDebtTokenImpl, underlyingAssetDecimals);
_initTokenWithProxy(
input.stableDebtTokenImpl,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
pool,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.stableDebtTokenName,
input.stableDebtTokenSymbol,
input.params
)
);
address variableDebtTokenProxyAddress =
_initTokenWithProxy(variableDebtTokenImpl, underlyingAssetDecimals);
_initTokenWithProxy(
input.variableDebtTokenImpl,
abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
pool,
input.underlyingAsset,
IAaveIncentivesController(input.incentivesController),
input.underlyingAssetDecimals,
input.variableDebtTokenName,
input.variableDebtTokenSymbol,
input.params
)
);
pool.initReserve(
asset,
input.underlyingAsset,
aTokenProxyAddress,
stableDebtTokenProxyAddress,
variableDebtTokenProxyAddress,
interestRateStrategyAddress
input.interestRateStrategyAddress
);
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);
DataTypes.ReserveConfigurationMap memory currentConfig =
pool.getConfiguration(input.underlyingAsset);
currentConfig.setDecimals(underlyingAssetDecimals);
currentConfig.setDecimals(input.underlyingAssetDecimals);
currentConfig.setActive(true);
currentConfig.setFrozen(false);
pool.setConfiguration(asset, currentConfig.data);
pool.setConfiguration(input.underlyingAsset, currentConfig.data);
emit ReserveInitialized(
asset,
input.underlyingAsset,
aTokenProxyAddress,
stableDebtTokenProxyAddress,
variableDebtTokenProxyAddress,
interestRateStrategyAddress
input.interestRateStrategyAddress
);
}
/**
* @dev Updates the aToken implementation for the reserve
* @param asset The address of the underlying asset of the reserve to be updated
* @param implementation The address of the new aToken implementation
**/
function updateAToken(address asset, address implementation) external onlyPoolAdmin {
DataTypes.ReserveData memory reserveData = pool.getReserveData(asset);
function updateAToken(UpdateATokenInput calldata input) external onlyPoolAdmin {
ILendingPool cachedPool = pool;
_upgradeTokenImplementation(asset, reserveData.aTokenAddress, implementation);
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
emit ATokenUpgraded(asset, reserveData.aTokenAddress, implementation);
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall = abi.encodeWithSelector(
IInitializableAToken.initialize.selector,
cachedPool,
input.treasury,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(
reserveData.aTokenAddress,
input.implementation,
encodedCall
);
emit ATokenUpgraded(input.asset, reserveData.aTokenAddress, input.implementation);
}
/**
* @dev Updates the stable debt token implementation for the reserve
* @param asset The address of the underlying asset of the reserve to be updated
* @param implementation The address of the new aToken implementation
**/
function updateStableDebtToken(address asset, address implementation) external onlyPoolAdmin {
DataTypes.ReserveData memory reserveData = pool.getReserveData(asset);
function updateStableDebtToken(UpdateDebtTokenInput calldata input) external onlyPoolAdmin {
ILendingPool cachedPool = pool;
_upgradeTokenImplementation(asset, reserveData.stableDebtTokenAddress, implementation);
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
emit StableDebtTokenUpgraded(asset, reserveData.stableDebtTokenAddress, implementation);
bytes memory encodedCall = abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
cachedPool,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(
reserveData.stableDebtTokenAddress,
input.implementation,
encodedCall
);
emit StableDebtTokenUpgraded(
input.asset,
reserveData.stableDebtTokenAddress,
input.implementation
);
}
/**
* @dev Updates the variable debt token implementation for the asset
* @param asset The address of the underlying asset of the reserve to be updated
* @param implementation The address of the new aToken implementation
**/
function updateVariableDebtToken(address asset, address implementation) external onlyPoolAdmin {
DataTypes.ReserveData memory reserveData = pool.getReserveData(asset);
function updateVariableDebtToken(UpdateDebtTokenInput calldata input)
external
onlyPoolAdmin
{
ILendingPool cachedPool = pool;
_upgradeTokenImplementation(asset, reserveData.variableDebtTokenAddress, implementation);
DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset);
emit VariableDebtTokenUpgraded(asset, reserveData.variableDebtTokenAddress, implementation);
(, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory();
bytes memory encodedCall = abi.encodeWithSelector(
IInitializableDebtToken.initialize.selector,
cachedPool,
input.asset,
input.incentivesController,
decimals,
input.name,
input.symbol,
input.params
);
_upgradeTokenImplementation(
reserveData.variableDebtTokenAddress,
input.implementation,
encodedCall
);
emit VariableDebtTokenUpgraded(
input.asset,
reserveData.variableDebtTokenAddress,
input.implementation
);
}
/**
@ -509,44 +451,27 @@ contract LendingPoolConfigurator is VersionedInitializable {
pool.setPause(val);
}
function _initTokenWithProxy(address implementation, uint8 decimals) internal returns (address) {
function _initTokenWithProxy(address implementation, bytes memory initParams)
internal
returns (address)
{
InitializableImmutableAdminUpgradeabilityProxy proxy =
new InitializableImmutableAdminUpgradeabilityProxy(address(this));
bytes memory params =
abi.encodeWithSignature(
'initialize(uint8,string,string)',
decimals,
IERC20Detailed(implementation).name(),
IERC20Detailed(implementation).symbol()
);
proxy.initialize(implementation, params);
proxy.initialize(implementation, initParams);
return address(proxy);
}
function _upgradeTokenImplementation(
address asset,
address proxyAddress,
address implementation
address implementation,
bytes memory initParams
) internal {
InitializableImmutableAdminUpgradeabilityProxy proxy =
InitializableImmutableAdminUpgradeabilityProxy(payable(proxyAddress));
DataTypes.ReserveConfigurationMap memory configuration = pool.getConfiguration(asset);
(, , , uint256 decimals, ) = configuration.getParamsMemory();
bytes memory params =
abi.encodeWithSignature(
'initialize(uint8,string,string)',
uint8(decimals),
IERC20Detailed(implementation).name(),
IERC20Detailed(implementation).symbol()
);
proxy.upgradeToAndCall(implementation, params);
proxy.upgradeToAndCall(implementation, initParams);
}
function _checkNoLiquidity(address asset) internal view {

View File

@ -23,4 +23,10 @@ contract LendingPoolStorage {
uint256 internal _reservesCount;
bool internal _paused;
uint256 internal _maxStableRateBorrowSizePercent;
uint256 internal _flashLoanPremiumTotal;
uint256 internal _maxNumberOfReserves;
}

View File

@ -50,14 +50,14 @@ abstract contract VersionedInitializable {
}
/**
* @dev returns the revision number of the contract
* Needs to be defined in the inherited class as a constant.
**/
* @dev returns the revision number of the contract
* Needs to be defined in the inherited class as a constant.
**/
function getRevision() internal pure virtual returns (uint256);
/**
* @dev Returns true if and only if the function is running in the constructor
**/
* @dev Returns true if and only if the function is running in the constructor
**/
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not

View File

@ -90,7 +90,10 @@ library ReserveConfiguration {
* @param self The reserve configuration
* @param bonus The new liquidation bonus
**/
function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus) internal pure {
function setLiquidationBonus(DataTypes.ReserveConfigurationMap memory self, uint256 bonus)
internal
pure
{
require(bonus <= MAX_VALID_LIQUIDATION_BONUS, Errors.RC_INVALID_LIQ_BONUS);
self.data =
@ -116,7 +119,10 @@ library ReserveConfiguration {
* @param self The reserve configuration
* @param decimals The decimals
**/
function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals) internal pure {
function setDecimals(DataTypes.ReserveConfigurationMap memory self, uint256 decimals)
internal
pure
{
require(decimals <= MAX_VALID_DECIMALS, Errors.RC_INVALID_DECIMALS);
self.data = (self.data & DECIMALS_MASK) | (decimals << RESERVE_DECIMALS_START_BIT_POSITION);
@ -127,7 +133,11 @@ library ReserveConfiguration {
* @param self The reserve configuration
* @return The decimals of the asset
**/
function getDecimals(DataTypes.ReserveConfigurationMap storage self) internal view returns (uint256) {
function getDecimals(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
{
return (self.data & ~DECIMALS_MASK) >> RESERVE_DECIMALS_START_BIT_POSITION;
}
@ -176,7 +186,10 @@ library ReserveConfiguration {
* @param self The reserve configuration
* @param enabled True if the borrowing needs to be enabled, false otherwise
**/
function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled) internal pure {
function setBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled)
internal
pure
{
self.data =
(self.data & BORROWING_MASK) |
(uint256(enabled ? 1 : 0) << BORROWING_ENABLED_START_BIT_POSITION);
@ -187,7 +200,11 @@ library ReserveConfiguration {
* @param self The reserve configuration
* @return The borrowing state
**/
function getBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self) internal view returns (bool) {
function getBorrowingEnabled(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (bool)
{
return (self.data & ~BORROWING_MASK) != 0;
}
@ -196,10 +213,10 @@ library ReserveConfiguration {
* @param self The reserve configuration
* @param enabled True if the stable rate borrowing needs to be enabled, false otherwise
**/
function setStableRateBorrowingEnabled(DataTypes.ReserveConfigurationMap memory self, bool enabled)
internal
pure
{
function setStableRateBorrowingEnabled(
DataTypes.ReserveConfigurationMap memory self,
bool enabled
) internal pure {
self.data =
(self.data & STABLE_BORROWING_MASK) |
(uint256(enabled ? 1 : 0) << STABLE_BORROWING_ENABLED_START_BIT_POSITION);
@ -239,7 +256,11 @@ library ReserveConfiguration {
* @param self The reserve configuration
* @return The reserve factor
**/
function getReserveFactor(DataTypes.ReserveConfigurationMap storage self) internal view returns (uint256) {
function getReserveFactor(DataTypes.ReserveConfigurationMap storage self)
internal
view
returns (uint256)
{
return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION;
}

View File

@ -53,11 +53,10 @@ library UserConfiguration {
* @param reserveIndex The index of the reserve in the bitmap
* @return True if the user has been using a reserve for borrowing or as collateral, false otherwise
**/
function isUsingAsCollateralOrBorrowing(DataTypes.UserConfigurationMap memory self, uint256 reserveIndex)
internal
pure
returns (bool)
{
function isUsingAsCollateralOrBorrowing(
DataTypes.UserConfigurationMap memory self,
uint256 reserveIndex
) internal pure returns (bool) {
require(reserveIndex < 128, Errors.UL_INVALID_INDEX);
return (self.data >> (reserveIndex * 2)) & 3 != 0;
}

View File

@ -65,7 +65,7 @@ library GenericLogic {
if (!userConfig.isBorrowingAny() || !userConfig.isUsingAsCollateral(reservesData[asset].id)) {
return true;
}
balanceDecreaseAllowedLocalVars memory vars;
(, vars.liquidationThreshold, , vars.decimals, ) = reservesData[asset]
@ -73,7 +73,7 @@ library GenericLogic {
.getParams();
if (vars.liquidationThreshold == 0) {
return true;
return true;
}
(
@ -213,9 +213,7 @@ library GenericLogic {
}
}
vars.avgLtv = vars.totalCollateralInETH > 0
? vars.avgLtv.div(vars.totalCollateralInETH)
: 0;
vars.avgLtv = vars.totalCollateralInETH > 0 ? vars.avgLtv.div(vars.totalCollateralInETH) : 0;
vars.avgLiquidationThreshold = vars.totalCollateralInETH > 0
? vars.avgLiquidationThreshold.div(vars.totalCollateralInETH)
: 0;
@ -265,8 +263,7 @@ library GenericLogic {
uint256 totalDebtInETH,
uint256 ltv
) internal pure returns (uint256) {
uint256 availableBorrowsETH = totalCollateralInETH.percentMul(ltv);
uint256 availableBorrowsETH = totalCollateralInETH.percentMul(ltv);
if (availableBorrowsETH < totalDebtInETH) {
return 0;

View File

@ -216,15 +216,15 @@ library ReserveLogic {
.scaledTotalSupply()
.rayMul(reserve.variableBorrowIndex);
vars.availableLiquidity = IERC20(reserveAddress).balanceOf(aTokenAddress);
(
vars.newLiquidityRate,
vars.newStableRate,
vars.newVariableRate
) = IReserveInterestRateStrategy(reserve.interestRateStrategyAddress).calculateInterestRates(
reserveAddress,
vars.availableLiquidity.add(liquidityAdded).sub(liquidityTaken),
aTokenAddress,
liquidityAdded,
liquidityTaken,
vars.totalStableDebt,
vars.totalVariableDebt,
vars.avgStableRate,

View File

@ -9,13 +9,18 @@ import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {VersionedInitializable} from '../libraries/aave-upgradeability/VersionedInitializable.sol';
import {IncentivizedERC20} from './IncentivizedERC20.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
/**
* @title Aave ERC20 AToken
* @dev Implementation of the interest bearing token for the Aave protocol
* @author Aave
*/
contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
contract AToken is
VersionedInitializable,
IncentivizedERC20('ATOKEN_IMPL', 'ATOKEN_IMPL', 0),
IAToken
{
using WadRayMath for uint256;
using SafeERC20 for IERC20;
@ -25,44 +30,47 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
bytes32 public constant PERMIT_TYPEHASH =
keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)');
uint256 public constant UINT_MAX_VALUE = uint256(-1);
uint256 public constant ATOKEN_REVISION = 0x1;
address public immutable UNDERLYING_ASSET_ADDRESS;
address public immutable RESERVE_TREASURY_ADDRESS;
ILendingPool public immutable POOL;
/// @dev owner => next valid nonce to submit with permit()
mapping(address => uint256) public _nonces;
bytes32 public DOMAIN_SEPARATOR;
modifier onlyLendingPool {
require(_msgSender() == address(POOL), Errors.CT_CALLER_MUST_BE_LENDING_POOL);
_;
}
ILendingPool internal _pool;
address internal _treasury;
address internal _underlyingAsset;
IAaveIncentivesController internal _incentivesController;
constructor(
ILendingPool pool,
address underlyingAssetAddress,
address reserveTreasuryAddress,
string memory tokenName,
string memory tokenSymbol,
address incentivesController
) public IncentivizedERC20(tokenName, tokenSymbol, 18, incentivesController) {
POOL = pool;
UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
RESERVE_TREASURY_ADDRESS = reserveTreasuryAddress;
modifier onlyLendingPool {
require(_msgSender() == address(_pool), Errors.CT_CALLER_MUST_BE_LENDING_POOL);
_;
}
function getRevision() internal pure virtual override returns (uint256) {
return ATOKEN_REVISION;
}
/**
* @dev Initializes the aToken
* @param pool The address of the lending pool where this aToken will be used
* @param treasury The address of the Aave treasury, receiving the fees on this aToken
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @param incentivesController The smart contract managing potential incentives distribution
* @param aTokenDecimals The decimals of the aToken, same as the underlying asset's
* @param aTokenName The name of the aToken
* @param aTokenSymbol The symbol of the aToken
*/
function initialize(
uint8 underlyingAssetDecimals,
string calldata tokenName,
string calldata tokenSymbol
) external virtual initializer {
ILendingPool pool,
address treasury,
address underlyingAsset,
IAaveIncentivesController incentivesController,
uint8 aTokenDecimals,
string calldata aTokenName,
string calldata aTokenSymbol,
bytes calldata params
) external override initializer {
uint256 chainId;
//solium-disable-next-line
@ -73,16 +81,32 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
DOMAIN_SEPARATOR = keccak256(
abi.encode(
EIP712_DOMAIN,
keccak256(bytes(tokenName)),
keccak256(bytes(aTokenName)),
keccak256(EIP712_REVISION),
chainId,
address(this)
)
);
_setName(tokenName);
_setSymbol(tokenSymbol);
_setDecimals(underlyingAssetDecimals);
_setName(aTokenName);
_setSymbol(aTokenSymbol);
_setDecimals(aTokenDecimals);
_pool = pool;
_treasury = treasury;
_underlyingAsset = underlyingAsset;
_incentivesController = incentivesController;
emit Initialized(
underlyingAsset,
address(pool),
treasury,
address(incentivesController),
aTokenDecimals,
aTokenName,
aTokenSymbol,
params
);
}
/**
@ -103,7 +127,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
require(amountScaled != 0, Errors.CT_INVALID_BURN_AMOUNT);
_burn(user, amountScaled);
IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount);
IERC20(_underlyingAsset).safeTransfer(receiverOfUnderlying, amount);
emit Transfer(user, address(0), amount);
emit Burn(user, receiverOfUnderlying, amount, index);
@ -145,14 +169,16 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
return;
}
address treasury = _treasury;
// Compared to the normal mint, we don't check for rounding errors.
// The amount to mint can easily be very small since it is a fraction of the interest ccrued.
// In that case, the treasury will experience a (very small) loss, but it
// wont cause potentially valid transactions to fail.
_mint(RESERVE_TREASURY_ADDRESS, amount.rayDiv(index));
_mint(treasury, amount.rayDiv(index));
emit Transfer(address(0), RESERVE_TREASURY_ADDRESS, amount);
emit Mint(RESERVE_TREASURY_ADDRESS, amount, index);
emit Transfer(address(0), treasury, amount);
emit Mint(treasury, amount, index);
}
/**
@ -185,7 +211,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
override(IncentivizedERC20, IERC20)
returns (uint256)
{
return super.balanceOf(user).rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS));
return super.balanceOf(user).rayMul(_pool.getReserveNormalizedIncome(_underlyingAsset));
}
/**
@ -226,7 +252,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
return 0;
}
return currentSupplyScaled.rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS));
return currentSupplyScaled.rayMul(_pool.getReserveNormalizedIncome(_underlyingAsset));
}
/**
@ -237,6 +263,41 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
return super.totalSupply();
}
/**
* @dev Returns the address of the Aave treasury, receiving the fees on this aToken
**/
function RESERVE_TREASURY_ADDRESS() public view returns (address) {
return _treasury;
}
/**
* @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
**/
function UNDERLYING_ASSET_ADDRESS() public override view returns (address) {
return _underlyingAsset;
}
/**
* @dev Returns the address of the lending pool where this aToken is used
**/
function POOL() public view returns (ILendingPool) {
return _pool;
}
/**
* @dev For internal usage in the logic of the parent contract IncentivizedERC20
**/
function _getIncentivesController() internal view override returns (IAaveIncentivesController) {
return _incentivesController;
}
/**
* @dev Returns the address of the incentives controller contract
**/
function getIncentivesController() external view override returns (IAaveIncentivesController) {
return _getIncentivesController();
}
/**
* @dev Transfers the underlying asset to `target`. Used by the LendingPool to transfer
* assets in borrow(), withdraw() and flashLoan()
@ -250,10 +311,17 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
onlyLendingPool
returns (uint256)
{
IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(target, amount);
IERC20(_underlyingAsset).safeTransfer(target, amount);
return amount;
}
/**
* @dev Invoked to execute actions on the aToken side after a repayment.
* @param user The user executing the repayment
* @param amount The amount getting repaid
**/
function handleRepayment(address user, uint256 amount) external override onlyLendingPool {}
/**
* @dev implements the permit function as for
* https://github.com/ethereum/EIPs/blob/8a34d644aacf0f9f8f00815307fd7dd5da07655f/EIPS/eip-2612.md
@ -305,7 +373,10 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
uint256 amount,
bool validate
) internal {
uint256 index = POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS);
address underlyingAsset = _underlyingAsset;
ILendingPool pool = _pool;
uint256 index = pool.getReserveNormalizedIncome(underlyingAsset);
uint256 fromBalanceBefore = super.balanceOf(from).rayMul(index);
uint256 toBalanceBefore = super.balanceOf(to).rayMul(index);
@ -313,14 +384,7 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
super._transfer(from, to, amount.rayDiv(index));
if (validate) {
POOL.finalizeTransfer(
UNDERLYING_ASSET_ADDRESS,
from,
to,
amount,
fromBalanceBefore,
toBalanceBefore
);
pool.finalizeTransfer(underlyingAsset, from, to, amount, fromBalanceBefore, toBalanceBefore);
}
emit BalanceTransfer(from, to, amount, index);

View File

@ -14,36 +14,17 @@ import {AToken} from './AToken.sol';
contract DelegationAwareAToken is AToken {
modifier onlyPoolAdmin {
require(
_msgSender() == ILendingPool(POOL).getAddressesProvider().getPoolAdmin(),
_msgSender() == ILendingPool(_pool).getAddressesProvider().getPoolAdmin(),
Errors.CALLER_NOT_POOL_ADMIN
);
_;
}
constructor(
ILendingPool pool,
address underlyingAssetAddress,
address reserveTreasury,
string memory tokenName,
string memory tokenSymbol,
address incentivesController
)
public
AToken(
pool,
underlyingAssetAddress,
reserveTreasury,
tokenName,
tokenSymbol,
incentivesController
)
{}
/**
* @dev Delegates voting power of the underlying asset to a `delegatee` address
* @param delegatee The address that will receive the delegation
**/
function delegateUnderlyingTo(address delegatee) external onlyPoolAdmin {
IDelegationToken(UNDERLYING_ASSET_ADDRESS).delegate(delegatee);
IDelegationToken(_underlyingAsset).delegate(delegatee);
}
}

View File

@ -12,11 +12,9 @@ import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesControl
* @notice Basic ERC20 implementation
* @author Aave, inspired by the Openzeppelin ERC20 implementation
**/
contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
abstract contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
using SafeMath for uint256;
IAaveIncentivesController internal immutable _incentivesController;
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) private _allowances;
@ -28,13 +26,11 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
constructor(
string memory name,
string memory symbol,
uint8 decimals,
address incentivesController
uint8 decimals
) public {
_name = name;
_symbol = symbol;
_decimals = decimals;
_incentivesController = IAaveIncentivesController(incentivesController);
}
/**
@ -72,6 +68,12 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
return _balances[account];
}
/**
* @return Abstract function implemented by the child aToken/debtToken.
* Done this way in order to not break compatibility with previous versions of aTokens/debtTokens
**/
function _getIncentivesController() internal view virtual returns(IAaveIncentivesController);
/**
* @dev Executes a transfer of tokens from _msgSender() to recipient
* @param recipient The recipient of the tokens
@ -180,11 +182,11 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
uint256 oldRecipientBalance = _balances[recipient];
_balances[recipient] = _balances[recipient].add(amount);
if (address(_incentivesController) != address(0)) {
if (address(_getIncentivesController()) != address(0)) {
uint256 currentTotalSupply = _totalSupply;
_incentivesController.handleAction(sender, currentTotalSupply, oldSenderBalance);
_getIncentivesController().handleAction(sender, currentTotalSupply, oldSenderBalance);
if (sender != recipient) {
_incentivesController.handleAction(recipient, currentTotalSupply, oldRecipientBalance);
_getIncentivesController().handleAction(recipient, currentTotalSupply, oldRecipientBalance);
}
}
}
@ -200,8 +202,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
uint256 oldAccountBalance = _balances[account];
_balances[account] = oldAccountBalance.add(amount);
if (address(_incentivesController) != address(0)) {
_incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance);
if (address(_getIncentivesController()) != address(0)) {
_getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance);
}
}
@ -216,8 +218,8 @@ contract IncentivizedERC20 is Context, IERC20, IERC20Detailed {
uint256 oldAccountBalance = _balances[account];
_balances[account] = oldAccountBalance.sub(amount, 'ERC20: burn amount exceeds balance');
if (address(_incentivesController) != address(0)) {
_incentivesController.handleAction(account, oldTotalSupply, oldAccountBalance);
if (address(_getIncentivesController()) != address(0)) {
_getIncentivesController().handleAction(account, oldTotalSupply, oldAccountBalance);
}
}

View File

@ -5,6 +5,8 @@ import {DebtTokenBase} from './base/DebtTokenBase.sol';
import {MathUtils} from '../libraries/math/MathUtils.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {IStableDebtToken} from '../../interfaces/IStableDebtToken.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
/**
@ -23,13 +25,46 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
mapping(address => uint256) internal _usersStableRate;
uint40 internal _totalSupplyTimestamp;
constructor(
address pool,
ILendingPool internal _pool;
address internal _underlyingAsset;
IAaveIncentivesController internal _incentivesController;
/**
* @dev Initializes the debt token.
* @param pool The address of the lending pool where this aToken will be used
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @param incentivesController The smart contract managing potential incentives distribution
* @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's
* @param debtTokenName The name of the token
* @param debtTokenSymbol The symbol of the token
*/
function initialize(
ILendingPool pool,
address underlyingAsset,
string memory name,
string memory symbol,
address incentivesController
) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {}
IAaveIncentivesController incentivesController,
uint8 debtTokenDecimals,
string memory debtTokenName,
string memory debtTokenSymbol,
bytes calldata params
) public override initializer {
_setName(debtTokenName);
_setSymbol(debtTokenSymbol);
_setDecimals(debtTokenDecimals);
_pool = pool;
_underlyingAsset = underlyingAsset;
_incentivesController = incentivesController;
emit Initialized(
underlyingAsset,
address(pool),
address(incentivesController),
debtTokenDecimals,
debtTokenName,
debtTokenSymbol,
params
);
}
/**
* @dev Gets the revision of the stable debt token implementation
@ -300,6 +335,48 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
return super.balanceOf(user);
}
/**
* @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
**/
function UNDERLYING_ASSET_ADDRESS() public view returns (address) {
return _underlyingAsset;
}
/**
* @dev Returns the address of the lending pool where this aToken is used
**/
function POOL() public view returns (ILendingPool) {
return _pool;
}
/**
* @dev Returns the address of the incentives controller contract
**/
function getIncentivesController() external view override returns (IAaveIncentivesController) {
return _getIncentivesController();
}
/**
* @dev For internal usage in the logic of the parent contracts
**/
function _getIncentivesController() internal view override returns (IAaveIncentivesController) {
return _incentivesController;
}
/**
* @dev For internal usage in the logic of the parent contracts
**/
function _getUnderlyingAssetAddress() internal view override returns (address) {
return _underlyingAsset;
}
/**
* @dev For internal usage in the logic of the parent contracts
**/
function _getLendingPool() internal view override returns (ILendingPool) {
return _pool;
}
/**
* @dev Calculates the total supply
* @param avgRate The average rate at which the total supply increases

View File

@ -5,6 +5,8 @@ import {IVariableDebtToken} from '../../interfaces/IVariableDebtToken.sol';
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
import {Errors} from '../libraries/helpers/Errors.sol';
import {DebtTokenBase} from './base/DebtTokenBase.sol';
import {ILendingPool} from '../../interfaces/ILendingPool.sol';
import {IAaveIncentivesController} from '../../interfaces/IAaveIncentivesController.sol';
/**
* @title VariableDebtToken
@ -17,13 +19,46 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
uint256 public constant DEBT_TOKEN_REVISION = 0x1;
constructor(
address pool,
ILendingPool internal _pool;
address internal _underlyingAsset;
IAaveIncentivesController internal _incentivesController;
/**
* @dev Initializes the debt token.
* @param pool The address of the lending pool where this aToken will be used
* @param underlyingAsset The address of the underlying asset of this aToken (E.g. WETH for aWETH)
* @param incentivesController The smart contract managing potential incentives distribution
* @param debtTokenDecimals The decimals of the debtToken, same as the underlying asset's
* @param debtTokenName The name of the token
* @param debtTokenSymbol The symbol of the token
*/
function initialize(
ILendingPool pool,
address underlyingAsset,
string memory name,
string memory symbol,
address incentivesController
) public DebtTokenBase(pool, underlyingAsset, name, symbol, incentivesController) {}
IAaveIncentivesController incentivesController,
uint8 debtTokenDecimals,
string memory debtTokenName,
string memory debtTokenSymbol,
bytes calldata params
) public override initializer {
_setName(debtTokenName);
_setSymbol(debtTokenSymbol);
_setDecimals(debtTokenDecimals);
_pool = pool;
_underlyingAsset = underlyingAsset;
_incentivesController = incentivesController;
emit Initialized(
underlyingAsset,
address(pool),
address(incentivesController),
debtTokenDecimals,
debtTokenName,
debtTokenSymbol,
params
);
}
/**
* @dev Gets the revision of the stable debt token implementation
@ -44,7 +79,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
return 0;
}
return scaledBalance.rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
return scaledBalance.rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset));
}
/**
@ -113,8 +148,7 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
* @return The total supply
**/
function totalSupply() public view virtual override returns (uint256) {
return
super.totalSupply().rayMul(POOL.getReserveNormalizedVariableDebt(UNDERLYING_ASSET_ADDRESS));
return super.totalSupply().rayMul(_pool.getReserveNormalizedVariableDebt(_underlyingAsset));
}
/**
@ -139,4 +173,37 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
{
return (super.balanceOf(user), super.totalSupply());
}
/**
* @dev Returns the address of the underlying asset of this aToken (E.g. WETH for aWETH)
**/
function UNDERLYING_ASSET_ADDRESS() public view returns (address) {
return _underlyingAsset;
}
/**
* @dev Returns the address of the incentives controller contract
**/
function getIncentivesController() external view override returns (IAaveIncentivesController) {
return _getIncentivesController();
}
/**
* @dev Returns the address of the lending pool where this aToken is used
**/
function POOL() public view returns (ILendingPool) {
return _pool;
}
function _getIncentivesController() internal view override returns (IAaveIncentivesController) {
return _incentivesController;
}
function _getUnderlyingAssetAddress() internal view override returns (address) {
return _underlyingAsset;
}
function _getLendingPool() internal view override returns (ILendingPool) {
return _pool;
}
}

View File

@ -16,54 +16,20 @@ import {Errors} from '../../libraries/helpers/Errors.sol';
*/
abstract contract DebtTokenBase is
IncentivizedERC20,
IncentivizedERC20('DEBTTOKEN_IMPL', 'DEBTTOKEN_IMPL', 0),
VersionedInitializable,
ICreditDelegationToken
{
address public immutable UNDERLYING_ASSET_ADDRESS;
ILendingPool public immutable POOL;
mapping(address => mapping(address => uint256)) internal _borrowAllowances;
/**
* @dev Only lending pool can call functions marked by this modifier
**/
modifier onlyLendingPool {
require(_msgSender() == address(POOL), Errors.CT_CALLER_MUST_BE_LENDING_POOL);
require(_msgSender() == address(_getLendingPool()), Errors.CT_CALLER_MUST_BE_LENDING_POOL);
_;
}
/**
* @dev The metadata of the token will be set on the proxy, that the reason of
* passing "NULL" and 0 as metadata
*/
constructor(
address pool,
address underlyingAssetAddress,
string memory name,
string memory symbol,
address incentivesController
) public IncentivizedERC20(name, symbol, 18, incentivesController) {
POOL = ILendingPool(pool);
UNDERLYING_ASSET_ADDRESS = underlyingAssetAddress;
}
/**
* @dev Initializes the debt token.
* @param name The name of the token
* @param symbol The symbol of the token
* @param decimals The decimals of the token
*/
function initialize(
uint8 decimals,
string memory name,
string memory symbol
) public initializer {
_setName(name);
_setSymbol(symbol);
_setDecimals(decimals);
}
/**
* @dev delegates borrowing power to a user on the specific debt token
* @param delegatee the address receiving the delegated borrowing power
@ -73,7 +39,7 @@ abstract contract DebtTokenBase is
**/
function approveDelegation(address delegatee, uint256 amount) external override {
_borrowAllowances[_msgSender()][delegatee] = amount;
emit BorrowAllowanceDelegated(_msgSender(), delegatee, UNDERLYING_ASSET_ADDRESS, amount);
emit BorrowAllowanceDelegated(_msgSender(), delegatee, _getUnderlyingAssetAddress(), amount);
}
/**
@ -162,6 +128,10 @@ abstract contract DebtTokenBase is
_borrowAllowances[delegator][delegatee] = newAllowance;
emit BorrowAllowanceDelegated(delegator, delegatee, UNDERLYING_ASSET_ADDRESS, newAllowance);
emit BorrowAllowanceDelegated(delegator, delegatee, _getUnderlyingAssetAddress(), newAllowance);
}
function _getUnderlyingAssetAddress() internal view virtual returns (address);
function _getLendingPool() internal view virtual returns (ILendingPool);
}

View File

@ -19,3 +19,5 @@ services:
TENDERLY_PROJECT: ${TENDERLY_PROJECT}
TENDERLY_USERNAME: ${TENDERLY_USERNAME}
ALCHEMY_KEY: ${ALCHEMY_KEY}
TENDERLY_FORK_ID: ${TENDERLY_FORK_ID}
TENDERLY_HEAD_ID: ${TENDERLY_HEAD_ID}

View File

@ -3,8 +3,9 @@ import fs from 'fs';
import { HardhatUserConfig } from 'hardhat/types';
// @ts-ignore
import { accounts } from './test-wallets.js';
import { eEthereumNetwork } from './helpers/types';
import { eEthereumNetwork, eNetwork, ePolygonNetwork, eXDaiNetwork } from './helpers/types';
import { BUIDLEREVM_CHAINID, COVERAGE_CHAINID } from './helpers/buidler-constants';
import { NETWORKS_RPC_URL, NETWORKS_DEFAULT_GAS } from './helper-hardhat-config';
require('dotenv').config();
@ -14,14 +15,12 @@ import 'temp-hardhat-etherscan';
import 'hardhat-gas-reporter';
import 'hardhat-typechain';
import '@tenderly/hardhat-tenderly';
import 'solidity-coverage';
const SKIP_LOAD = process.env.SKIP_LOAD === 'true';
const DEFAULT_BLOCK_GAS_LIMIT = 12450000;
const DEFAULT_GAS_MUL = 5;
const DEFAULT_GAS_PRICE = 65000000000;
const HARDFORK = 'istanbul';
const INFURA_KEY = process.env.INFURA_KEY || '';
const ALCHEMY_KEY = process.env.ALCHEMY_KEY || '';
const ETHERSCAN_KEY = process.env.ETHERSCAN_KEY || '';
const MNEMONIC_PATH = "m/44'/60'/0'/0";
const MNEMONIC = process.env.MNEMONIC || '';
@ -43,32 +42,25 @@ if (!SKIP_LOAD) {
require(`${path.join(__dirname, 'tasks/misc')}/set-bre.ts`);
const getCommonNetworkConfig = (networkName: eEthereumNetwork, networkId: number) => {
const net = networkName === 'main' ? 'mainnet' : networkName;
return {
url: ALCHEMY_KEY
? `https://eth-${net}.alchemyapi.io/v2/${ALCHEMY_KEY}`
: `https://${net}.infura.io/v3/${INFURA_KEY}`,
hardfork: HARDFORK,
blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT,
gasMultiplier: DEFAULT_GAS_MUL,
gasPrice: DEFAULT_GAS_PRICE,
chainId: networkId,
accounts: {
mnemonic: MNEMONIC,
path: MNEMONIC_PATH,
initialIndex: 0,
count: 20,
},
};
};
const getCommonNetworkConfig = (networkName: eNetwork, networkId: number) => ({
url: NETWORKS_RPC_URL[networkName],
hardfork: HARDFORK,
blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT,
gasMultiplier: DEFAULT_GAS_MUL,
gasPrice: NETWORKS_DEFAULT_GAS[networkName],
chainId: networkId,
accounts: {
mnemonic: MNEMONIC,
path: MNEMONIC_PATH,
initialIndex: 0,
count: 20,
},
});
const mainnetFork = MAINNET_FORK
? {
blockNumber: 11608298,
url: ALCHEMY_KEY
? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}`
: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
blockNumber: 12012081,
url: NETWORKS_RPC_URL['main'],
}
: undefined;
@ -103,9 +95,12 @@ const buidlerConfig: HardhatUserConfig = {
kovan: getCommonNetworkConfig(eEthereumNetwork.kovan, 42),
ropsten: getCommonNetworkConfig(eEthereumNetwork.ropsten, 3),
main: getCommonNetworkConfig(eEthereumNetwork.main, 1),
tenderlyMain: getCommonNetworkConfig(eEthereumNetwork.main, 1),
tenderlyMain: getCommonNetworkConfig(eEthereumNetwork.tenderlyMain, 3030),
matic: getCommonNetworkConfig(ePolygonNetwork.matic, 137),
mumbai: getCommonNetworkConfig(ePolygonNetwork.mumbai, 80001),
xdai: getCommonNetworkConfig(eXDaiNetwork.xdai, 100),
hardhat: {
hardfork: 'istanbul',
hardfork: 'berlin',
blockGasLimit: DEFAULT_BLOCK_GAS_LIMIT,
gas: DEFAULT_BLOCK_GAS_LIMIT,
gasPrice: 8000000000,
@ -119,7 +114,7 @@ const buidlerConfig: HardhatUserConfig = {
forking: mainnetFork,
},
buidlerevm_docker: {
hardfork: 'istanbul',
hardfork: 'berlin',
blockGasLimit: 9500000,
gas: 9500000,
gasPrice: 8000000000,

47
helper-hardhat-config.ts Normal file
View File

@ -0,0 +1,47 @@
// @ts-ignore
import {
eEthereumNetwork,
ePolygonNetwork,
eXDaiNetwork,
iParamsPerNetwork,
} from './helpers/types';
require('dotenv').config();
const INFURA_KEY = process.env.INFURA_KEY || '';
const ALCHEMY_KEY = process.env.ALCHEMY_KEY || '';
const TENDERLY_FORK_ID = process.env.TENDERLY_FORK_ID || '';
const GWEI = 1000 * 1000 * 1000;
export const NETWORKS_RPC_URL: iParamsPerNetwork<string> = {
[eEthereumNetwork.kovan]: ALCHEMY_KEY
? `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_KEY}`
: `https://kovan.infura.io/v3/${INFURA_KEY}`,
[eEthereumNetwork.ropsten]: ALCHEMY_KEY
? `https://eth-ropsten.alchemyapi.io/v2/${ALCHEMY_KEY}`
: `https://ropsten.infura.io/v3/${INFURA_KEY}`,
[eEthereumNetwork.main]: ALCHEMY_KEY
? `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_KEY}`
: `https://mainnet.infura.io/v3/${INFURA_KEY}`,
[eEthereumNetwork.coverage]: 'http://localhost:8555',
[eEthereumNetwork.hardhat]: 'http://localhost:8545',
[eEthereumNetwork.buidlerevm]: 'http://localhost:8545',
[eEthereumNetwork.tenderlyMain]: `https://rpc.tenderly.co/fork/${TENDERLY_FORK_ID}`,
[ePolygonNetwork.mumbai]: 'https://rpc-mumbai.maticvigil.com',
[ePolygonNetwork.matic]: 'https://rpc-mainnet.matic.network',
[eXDaiNetwork.xdai]: 'https://rpc.xdaichain.com/',
};
export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork<number> = {
[eEthereumNetwork.kovan]: 65 * GWEI,
[eEthereumNetwork.ropsten]: 65 * GWEI,
[eEthereumNetwork.main]: 65 * GWEI,
[eEthereumNetwork.coverage]: 65 * GWEI,
[eEthereumNetwork.hardhat]: 65 * GWEI,
[eEthereumNetwork.buidlerevm]: 65 * GWEI,
[eEthereumNetwork.tenderlyMain]: 0.01 * GWEI,
[ePolygonNetwork.mumbai]: 1 * GWEI,
[ePolygonNetwork.matic]: 2 * GWEI,
[eXDaiNetwork.xdai]: 1 * GWEI,
};

View File

@ -4,10 +4,12 @@ import {
IReserveParams,
PoolConfiguration,
ICommonConfiguration,
eEthereumNetwork,
eNetwork,
} from './types';
import { getParamPerPool } from './contracts-helpers';
import AaveConfig from '../markets/aave';
import MaticConfig from '../markets/matic';
import AmmConfig from '../markets/amm';
import { CommonsConfig } from '../markets/aave/commons';
import { DRE, filterMapBy } from './misc-utils';
import { tEthereumAddress } from './types';
@ -17,13 +19,18 @@ import { deployWETHMocked } from './contracts-deployments';
export enum ConfigNames {
Commons = 'Commons',
Aave = 'Aave',
Uniswap = 'Uniswap',
Matic = 'Matic',
Amm = 'Amm',
}
export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => {
switch (configName) {
case ConfigNames.Aave:
return AaveConfig;
case ConfigNames.Matic:
return MaticConfig;
case ConfigNames.Amm:
return AmmConfig;
case ConfigNames.Commons:
return CommonsConfig;
default:
@ -41,6 +48,12 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets<IRes
[AavePools.proto]: {
...AaveConfig.ReservesConfig,
},
[AavePools.amm]: {
...AmmConfig.ReservesConfig,
},
[AavePools.matic]: {
...MaticConfig.ReservesConfig,
},
},
pool
);
@ -49,7 +62,7 @@ export const getGenesisPoolAdmin = async (
config: ICommonConfiguration
): Promise<tEthereumAddress> => {
const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name;
const targetAddress = getParamPerNetwork(config.PoolAdmin, <eEthereumNetwork>currentNetwork);
const targetAddress = getParamPerNetwork(config.PoolAdmin, <eNetwork>currentNetwork);
if (targetAddress) {
return targetAddress;
}
@ -64,7 +77,7 @@ export const getEmergencyAdmin = async (
config: ICommonConfiguration
): Promise<tEthereumAddress> => {
const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name;
const targetAddress = getParamPerNetwork(config.EmergencyAdmin, <eEthereumNetwork>currentNetwork);
const targetAddress = getParamPerNetwork(config.EmergencyAdmin, <eNetwork>currentNetwork);
if (targetAddress) {
return targetAddress;
}
@ -79,17 +92,17 @@ export const getTreasuryAddress = async (
config: ICommonConfiguration
): Promise<tEthereumAddress> => {
const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name;
return getParamPerNetwork(config.ReserveFactorTreasuryAddress, <eEthereumNetwork>currentNetwork);
return getParamPerNetwork(config.ReserveFactorTreasuryAddress, <eNetwork>currentNetwork);
};
export const getATokenDomainSeparatorPerNetwork = (
network: eEthereumNetwork,
network: eNetwork,
config: ICommonConfiguration
): tEthereumAddress => getParamPerNetwork<tEthereumAddress>(config.ATokenDomainSeparator, network);
export const getWethAddress = async (config: ICommonConfiguration) => {
const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name;
const wethAddress = getParamPerNetwork(config.WETH, <eEthereumNetwork>currentNetwork);
const wethAddress = getParamPerNetwork(config.WETH, <eNetwork>currentNetwork);
if (wethAddress) {
return wethAddress;
}

View File

@ -28,3 +28,46 @@ export const TOKEN_DISTRIBUTOR_PERCENTAGE_BASE = '10000';
export const MOCK_USD_PRICE_IN_WEI = '5848466240000000';
export const USD_ADDRESS = '0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96';
export const AAVE_REFERRAL = '0';
export const MOCK_CHAINLINK_AGGREGATORS_PRICES = {
AAVE: oneEther.multipliedBy('0.003620948469').toFixed(),
BAT: oneEther.multipliedBy('0.00137893825230').toFixed(),
BUSD: oneEther.multipliedBy('0.00736484').toFixed(),
DAI: oneEther.multipliedBy('0.00369068412860').toFixed(),
ENJ: oneEther.multipliedBy('0.00029560').toFixed(),
KNC: oneEther.multipliedBy('0.001072').toFixed(),
LINK: oneEther.multipliedBy('0.009955').toFixed(),
MANA: oneEther.multipliedBy('0.000158').toFixed(),
MKR: oneEther.multipliedBy('2.508581').toFixed(),
REN: oneEther.multipliedBy('0.00065133').toFixed(),
SNX: oneEther.multipliedBy('0.00442616').toFixed(),
SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(),
TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(),
UNI: oneEther.multipliedBy('0.00536479').toFixed(),
USDC: oneEther.multipliedBy('0.00367714136416').toFixed(),
USDT: oneEther.multipliedBy('0.00369068412860').toFixed(),
WETH: oneEther.toFixed(),
WBTC: oneEther.multipliedBy('47.332685').toFixed(),
YFI: oneEther.multipliedBy('22.407436').toFixed(),
ZRX: oneEther.multipliedBy('0.001151').toFixed(),
UniDAIWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniAAVEWETH: oneEther.multipliedBy('0.003620948469').toFixed(),
UniBATWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniDAIUSDC: oneEther.multipliedBy('22.407436').toFixed(),
UniCRVWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniLINKWETH: oneEther.multipliedBy('0.009955').toFixed(),
UniMKRWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniRENWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniSNXWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniUNIWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniUSDCWETH: oneEther.multipliedBy('22.407436').toFixed(),
UniWBTCUSDC: oneEther.multipliedBy('22.407436').toFixed(),
UniYFIWETH: oneEther.multipliedBy('22.407436').toFixed(),
BptWBTCWETH: oneEther.multipliedBy('22.407436').toFixed(),
BptBALWETH: oneEther.multipliedBy('22.407436').toFixed(),
WMATIC: oneEther.multipliedBy('0.003620948469').toFixed(),
STAKE: oneEther.multipliedBy('0.003620948469').toFixed(),
xSUSHI: oneEther.multipliedBy('0.00913428586').toFixed(),
USD: '5848466240000000',
};

View File

@ -11,7 +11,6 @@ import {
PoolConfiguration,
eEthereumNetwork,
} from './types';
import { MintableERC20 } from '../types/MintableERC20';
import { MockContract } from 'ethereum-waffle';
import { getReservesConfigByPool } from './configuration';
@ -49,18 +48,35 @@ import {
WalletBalanceProviderFactory,
WETH9MockedFactory,
WETHGatewayFactory,
FlashLiquidationAdapterFactory,
} from '../types';
import {
withSaveAndVerify,
registerContractInJsonDb,
linkBytecode,
insertContractAddressInDb,
deployContract,
} from './contracts-helpers';
import { StableAndVariableTokensHelperFactory } from '../types/StableAndVariableTokensHelperFactory';
import { MintableDelegationERC20 } from '../types/MintableDelegationERC20';
import { readArtifact as buidlerReadArtifact } from '@nomiclabs/buidler/plugins';
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { LendingPoolLibraryAddresses } from '../types/LendingPoolFactory';
import { UiPoolDataProvider } from '../types';
import { verifyContract } from './etherscan-verification';
export const deployUiPoolDataProvider = async (
[incentivesController, aaveOracle]: [tEthereumAddress, tEthereumAddress],
verify?: boolean
) => {
const id = eContractid.UiPoolDataProvider;
const args: string[] = [incentivesController, aaveOracle];
const instance = await deployContract<UiPoolDataProvider>(id, args);
if (verify) {
await verifyContract(instance.address, args);
}
return instance;
};
const readArtifact = async (id: string) => {
if (DRE.network.name === eEthereumNetwork.buidlerevm) {
@ -68,6 +84,7 @@ const readArtifact = async (id: string) => {
}
return (DRE as HardhatRuntimeEnvironment).artifacts.readArtifact(id);
};
export const deployLendingPoolAddressesProvider = async (marketId: string, verify?: boolean) =>
withSaveAndVerify(
await new LendingPoolAddressesProviderFactory(await getFirstSigner()).deploy(marketId),
@ -299,82 +316,133 @@ export const deployDefaultReserveInterestRateStrategy = async (
);
export const deployStableDebtToken = async (
args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string],
verify: boolean
) =>
withSaveAndVerify(
await new StableDebtTokenFactory(await getFirstSigner()).deploy(...args),
) => {
const instance = await withSaveAndVerify(
await new StableDebtTokenFactory(await getFirstSigner()).deploy(),
eContractid.StableDebtToken,
args,
[],
verify
);
await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4], '0x10');
return instance;
};
export const deployVariableDebtToken = async (
args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string],
verify: boolean
) =>
withSaveAndVerify(
await new VariableDebtTokenFactory(await getFirstSigner()).deploy(...args),
) => {
const instance = await withSaveAndVerify(
await new VariableDebtTokenFactory(await getFirstSigner()).deploy(),
eContractid.VariableDebtToken,
args,
[],
verify
);
await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4], '0x10');
return instance;
};
export const deployGenericStableDebtToken = async () =>
withSaveAndVerify(
await new StableDebtTokenFactory(await getFirstSigner()).deploy(),
eContractid.StableDebtToken,
[],
false
);
export const deployGenericVariableDebtToken = async () =>
withSaveAndVerify(
await new VariableDebtTokenFactory(await getFirstSigner()).deploy(),
eContractid.VariableDebtToken,
[],
false
);
export const deployGenericAToken = async (
[poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]: [
[poolAddress, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [
tEthereumAddress,
tEthereumAddress,
tEthereumAddress,
tEthereumAddress,
string,
string,
tEthereumAddress
string
],
verify: boolean
) => {
const args: [
tEthereumAddress,
tEthereumAddress,
string,
string,
tEthereumAddress,
tEthereumAddress
] = [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController];
return withSaveAndVerify(
await new ATokenFactory(await getFirstSigner()).deploy(...args),
const instance = await withSaveAndVerify(
await new ATokenFactory(await getFirstSigner()).deploy(),
eContractid.AToken,
args,
[],
verify
);
await instance.initialize(
poolAddress,
treasuryAddress,
underlyingAssetAddress,
incentivesController,
'18',
name,
symbol,
'0x10'
);
return instance;
};
export const deployGenericATokenImpl = async (verify: boolean) =>
withSaveAndVerify(
await new ATokenFactory(await getFirstSigner()).deploy(),
eContractid.AToken,
[],
verify
);
export const deployDelegationAwareAToken = async (
[poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController]: [
[pool, underlyingAssetAddress, treasuryAddress, incentivesController, name, symbol]: [
tEthereumAddress,
tEthereumAddress,
tEthereumAddress,
tEthereumAddress,
string,
string,
tEthereumAddress
string
],
verify: boolean
) => {
const args: [
tEthereumAddress,
tEthereumAddress,
string,
string,
tEthereumAddress,
tEthereumAddress
] = [poolAddress, underlyingAssetAddress, treasuryAddress, name, symbol, incentivesController];
return withSaveAndVerify(
await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(...args),
const instance = await withSaveAndVerify(
await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(),
eContractid.DelegationAwareAToken,
args,
[],
verify
);
await instance.initialize(
pool,
treasuryAddress,
underlyingAssetAddress,
incentivesController,
'18',
name,
symbol,
'0x10'
);
return instance;
};
export const deployDelegationAwareATokenImpl = async (verify: boolean) =>
withSaveAndVerify(
await new DelegationAwareATokenFactory(await getFirstSigner()).deploy(),
eContractid.DelegationAwareAToken,
[],
verify
);
export const deployAllMockTokens = async (verify?: boolean) => {
const tokens: { [symbol: string]: MockContract | MintableERC20 } = {};
@ -389,6 +457,7 @@ export const deployAllMockTokens = async (verify?: boolean) => {
[tokenSymbol, tokenSymbol, configData ? configData.reserveDecimals : decimals],
verify
);
await registerContractInJsonDb(tokenSymbol.toUpperCase(), tokens[tokenSymbol]);
}
return tokens;
};
@ -436,10 +505,7 @@ export const deployATokensAndRatesHelper = async (
verify
);
export const deployWETHGateway = async (
args: [tEthereumAddress, tEthereumAddress],
verify?: boolean
) =>
export const deployWETHGateway = async (args: [tEthereumAddress], verify?: boolean) =>
withSaveAndVerify(
await new WETHGatewayFactory(await getFirstSigner()).deploy(...args),
eContractid.WETHGateway,
@ -447,17 +513,30 @@ export const deployWETHGateway = async (
verify
);
export const deployMockStableDebtToken = async (
args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
verify?: boolean
export const authorizeWETHGateway = async (
wethGateWay: tEthereumAddress,
lendingPool: tEthereumAddress
) =>
withSaveAndVerify(
await new MockStableDebtTokenFactory(await getFirstSigner()).deploy(...args),
await new WETHGatewayFactory(await getFirstSigner())
.attach(wethGateWay)
.authorizeLendingPool(lendingPool);
export const deployMockStableDebtToken = async (
args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, string],
verify?: boolean
) => {
const instance = await withSaveAndVerify(
await new MockStableDebtTokenFactory(await getFirstSigner()).deploy(),
eContractid.MockStableDebtToken,
args,
[],
verify
);
await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4], args[5]);
return instance;
};
export const deployWETHMocked = async (verify?: boolean) =>
withSaveAndVerify(
await new WETH9MockedFactory(await getFirstSigner()).deploy(),
@ -467,27 +546,45 @@ export const deployWETHMocked = async (verify?: boolean) =>
);
export const deployMockVariableDebtToken = async (
args: [tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, string],
verify?: boolean
) =>
withSaveAndVerify(
await new MockVariableDebtTokenFactory(await getFirstSigner()).deploy(...args),
) => {
const instance = await withSaveAndVerify(
await new MockVariableDebtTokenFactory(await getFirstSigner()).deploy(),
eContractid.MockVariableDebtToken,
args,
[],
verify
);
await instance.initialize(args[0], args[1], args[2], '18', args[3], args[4], args[5]);
return instance;
};
export const deployMockAToken = async (
args: [tEthereumAddress, tEthereumAddress, tEthereumAddress, string, string, tEthereumAddress],
args: [
tEthereumAddress,
tEthereumAddress,
tEthereumAddress,
tEthereumAddress,
string,
string,
string
],
verify?: boolean
) =>
withSaveAndVerify(
await new MockATokenFactory(await getFirstSigner()).deploy(...args),
) => {
const instance = await withSaveAndVerify(
await new MockATokenFactory(await getFirstSigner()).deploy(),
eContractid.MockAToken,
args,
[],
verify
);
await instance.initialize(args[0], args[2], args[1], args[3], '18', args[4], args[5], args[6]);
return instance;
};
export const deploySelfdestructTransferMock = async (verify?: boolean) =>
withSaveAndVerify(
await new SelfdestructTransferFactory(await getFirstSigner()).deploy(),
@ -525,3 +622,14 @@ export const deployUniswapRepayAdapter = async (
args,
verify
);
export const deployFlashLiquidationAdapter = async (
args: [tEthereumAddress, tEthereumAddress, tEthereumAddress],
verify?: boolean
) =>
withSaveAndVerify(
await new FlashLiquidationAdapterFactory(await getFirstSigner()).deploy(...args),
eContractid.FlashLiquidationAdapter,
args,
verify
);

View File

@ -29,6 +29,7 @@ import {
WalletBalanceProviderFactory,
WETH9MockedFactory,
WETHGatewayFactory,
FlashLiquidationAdapterFactory,
} from '../types';
import { IERC20DetailedFactory } from '../types/IERC20DetailedFactory';
import { MockTokenMap } from './contracts-helpers';
@ -174,16 +175,16 @@ export const getPairsTokenAggregator = (
const { ETH, USD, WETH, ...assetsAddressesWithoutEth } = allAssetsAddresses;
const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => {
if (tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH') {
const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex(
(value) => value === tokenSymbol
);
const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [
string,
tEthereumAddress
][])[aggregatorAddressIndex];
return [tokenAddress, aggregatorAddress];
}
//if (true/*tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH' && tokenSymbol !== 'LpWETH'*/) {
const aggregatorAddressIndex = Object.keys(aggregatorsAddresses).findIndex(
(value) => value === tokenSymbol
);
const [, aggregatorAddress] = (Object.entries(aggregatorsAddresses) as [
string,
tEthereumAddress
][])[aggregatorAddressIndex];
return [tokenAddress, aggregatorAddress];
//}
}) as [string, string][];
const mappedPairs = pairs.map(([asset]) => asset);
@ -354,3 +355,11 @@ export const getUniswapRepayAdapter = async (address?: tEthereumAddress) =>
(await getDb().get(`${eContractid.UniswapRepayAdapter}.${DRE.network.name}`).value()).address,
await getFirstSigner()
);
export const getFlashLiquidationAdapter = async (address?: tEthereumAddress) =>
await FlashLiquidationAdapterFactory.connect(
address ||
(await getDb().get(`${eContractid.FlashLiquidationAdapter}.${DRE.network.name}`).value())
.address,
await getFirstSigner()
);

View File

@ -11,12 +11,20 @@ import {
AavePools,
iParamsPerNetwork,
iParamsPerPool,
ePolygonNetwork,
eXDaiNetwork,
eNetwork,
iParamsPerNetworkAll,
iEthereumParamsPerNetwork,
iPolygonParamsPerNetwork,
iXDaiParamsPerNetwork,
} from './types';
import { MintableERC20 } from '../types/MintableERC20';
import { Artifact } from 'hardhat/types';
import { Artifact as BuidlerArtifact } from '@nomiclabs/buidler/types';
import { verifyContract } from './etherscan-verification';
import { getIErc20Detailed } from './contracts-getters';
import { usingTenderly } from './tenderly-utils';
export type MockTokenMap = { [symbol: string]: MintableERC20 };
@ -90,11 +98,15 @@ export const withSaveAndVerify = async <ContractType extends Contract>(
): Promise<ContractType> => {
await waitForTx(instance.deployTransaction);
await registerContractInJsonDb(id, instance);
if (DRE.network.name.includes('tenderly')) {
if (usingTenderly()) {
console.log();
console.log('Doing Tenderly contract verification of', id);
await (DRE as any).tenderlyRPC.verify({
name: id,
address: instance.address,
});
console.log(`Verified ${id} at Tenderly!`);
console.log();
}
if (verify) {
await verifyContract(instance.address, args);
@ -130,10 +142,17 @@ export const linkBytecode = (artifact: BuidlerArtifact | Artifact, libraries: an
return bytecode;
};
export const getParamPerNetwork = <T>(
{ kovan, ropsten, main, buidlerevm, coverage, tenderlyMain }: iParamsPerNetwork<T>,
network: eEthereumNetwork
) => {
export const getParamPerNetwork = <T>(param: iParamsPerNetwork<T>, network: eNetwork) => {
const {
main,
ropsten,
kovan,
coverage,
buidlerevm,
tenderlyMain,
} = param as iEthereumParamsPerNetwork<T>;
const { matic, mumbai } = param as iPolygonParamsPerNetwork<T>;
const { xdai } = param as iXDaiParamsPerNetwork<T>;
const MAINNET_FORK = process.env.MAINNET_FORK === 'true';
if (MAINNET_FORK) {
return main;
@ -154,13 +173,23 @@ export const getParamPerNetwork = <T>(
return main;
case eEthereumNetwork.tenderlyMain:
return tenderlyMain;
case ePolygonNetwork.matic:
return matic;
case ePolygonNetwork.mumbai:
return mumbai;
case eXDaiNetwork.xdai:
return xdai;
}
};
export const getParamPerPool = <T>({ proto }: iParamsPerPool<T>, pool: AavePools) => {
export const getParamPerPool = <T>({ proto, amm, matic }: iParamsPerPool<T>, pool: AavePools) => {
switch (pool) {
case AavePools.proto:
return proto;
case AavePools.amm:
return amm;
case AavePools.matic:
return matic;
default:
return proto;
}
@ -286,3 +315,16 @@ export const buildRepayAdapterParams = (
[collateralAsset, collateralAmount, rateMode, permitAmount, deadline, v, r, s, useEthPath]
);
};
export const buildFlashLiquidationAdapterParams = (
collateralAsset: tEthereumAddress,
debtAsset: tEthereumAddress,
user: tEthereumAddress,
debtToCover: BigNumberish,
useEthPath: boolean
) => {
return ethers.utils.defaultAbiCoder.encode(
['address', 'address', 'address', 'uint256', 'bool'],
[collateralAsset, debtAsset, user, debtToCover, useEthPath]
);
};

View File

@ -1,7 +1,7 @@
import {exit} from 'process';
import { exit } from 'process';
import fs from 'fs';
import {file} from 'tmp-promise';
import {DRE} from './misc-utils';
import { file } from 'tmp-promise';
import { DRE } from './misc-utils';
const fatalErrors = [
`The address provided as argument contains a contract, but its bytecode`,
@ -43,7 +43,7 @@ export const verifyContract = async (
const msDelay = 3000;
const times = 4;
// Write a temporal file to host complex parameters for buidler-etherscan https://github.com/nomiclabs/buidler/tree/development/packages/buidler-etherscan#complex-arguments
const {fd, path, cleanup} = await file({
const { fd, path, cleanup } = await file({
prefix: 'verify-params-',
postfix: '.js',
});

View File

@ -1,6 +1,7 @@
import {
eContractid,
eEthereumNetwork,
eNetwork,
iMultiPoolsAssets,
IReserveParams,
tEthereumAddress,
@ -12,6 +13,7 @@ import {
getAToken,
getATokensAndRatesHelper,
getLendingPoolAddressesProvider,
getLendingPoolConfiguratorProxy,
getStableAndVariableTokensHelper,
} from './contracts-getters';
import { rawInsertContractAddressInDb } from './contracts-helpers';
@ -19,12 +21,17 @@ import { BigNumber, BigNumberish, Signer } from 'ethers';
import {
deployDefaultReserveInterestRateStrategy,
deployDelegationAwareAToken,
deployDelegationAwareATokenImpl,
deployGenericAToken,
deployGenericATokenImpl,
deployGenericStableDebtToken,
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) {
@ -40,6 +47,10 @@ export const chooseATokenDeployment = (id: eContractid) => {
export const initReservesByHelper = async (
reservesParams: iMultiPoolsAssets<IReserveParams>,
tokenAddresses: { [symbol: string]: tEthereumAddress },
aTokenNamePrefix: string,
stableDebtTokenNamePrefix: string,
variableDebtTokenNamePrefix: string,
symbolPrefix: string,
admin: tEthereumAddress,
treasuryAddress: tEthereumAddress,
incentivesController: tEthereumAddress,
@ -47,139 +58,93 @@ export const initReservesByHelper = async (
): Promise<BigNumber> => {
let gasUsage = BigNumber.from('0');
const stableAndVariableDeployer = await getStableAndVariableTokensHelper();
const atokenAndRatesDeployer = await getATokensAndRatesHelper();
const addressProvider = await getLendingPoolAddressesProvider();
const poolAddress = await addressProvider.getLendingPool();
// Set aTokenAndRatesDeployer as temporal admin
await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address));
// CHUNK CONFIGURATION
const tokensChunks = 2;
const initChunks = 4;
// Deploy tokens and rates that uses common aToken in chunks
const reservesChunks = chunk(
Object.entries(reservesParams).filter(
([_, { aTokenImpl }]) => aTokenImpl === eContractid.AToken
) as [string, IReserveParams][],
tokensChunks
);
// Initialize variables for future reserves initialization
let deployedStableTokens: string[] = [];
let deployedVariableTokens: string[] = [];
let deployedATokens: string[] = [];
let deployedRates: string[] = [];
let reserveTokens: string[] = [];
let reserveInitDecimals: string[] = [];
let reserveSymbols: string[] = [];
console.log(
`- Token deployments in ${reservesChunks.length * 2} txs instead of ${
Object.entries(reservesParams).length * 4
} txs`
);
for (let reservesChunk of reservesChunks) {
// Prepare data
const tokens: string[] = [];
const symbols: string[] = [];
const strategyRates: [
BigNumberish,
BigNumberish,
BigNumberish,
BigNumberish,
BigNumberish,
BigNumberish
][] = [];
const reservesDecimals: string[] = [];
let initInputParams: {
aTokenImpl: string;
stableDebtTokenImpl: string;
variableDebtTokenImpl: string;
underlyingAssetDecimals: BigNumberish;
interestRateStrategyAddress: string;
underlyingAsset: string;
treasury: string;
incentivesController: string;
underlyingAssetName: string;
aTokenName: string;
aTokenSymbol: string;
variableDebtTokenName: string;
variableDebtTokenSymbol: string;
stableDebtTokenName: string;
stableDebtTokenSymbol: string;
params: string;
}[] = [];
for (let [assetSymbol, { reserveDecimals }] of reservesChunk) {
const assetAddressIndex = Object.keys(tokenAddresses).findIndex(
(value) => value === assetSymbol
);
const [, tokenAddress] = (Object.entries(tokenAddresses) as [string, string][])[
assetAddressIndex
];
let strategyRates: [
string, // addresses provider
string,
string,
string,
string,
string,
string
];
let rateStrategies: Record<string, typeof strategyRates> = {};
let strategyAddresses: Record<string, tEthereumAddress> = {};
let strategyAddressPerAsset: Record<string, string> = {};
let aTokenType: Record<string, string> = {};
let delegationAwareATokenImplementationAddress = '';
let aTokenImplementationAddress = '';
let stableDebtTokenImplementationAddress = '';
let variableDebtTokenImplementationAddress = '';
const reserveParamIndex = Object.keys(reservesParams).findIndex(
(value) => value === assetSymbol
);
const [
,
{
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
},
] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex];
// Add to lists
tokens.push(tokenAddress);
symbols.push(assetSymbol);
strategyRates.push([
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
]);
reservesDecimals.push(reserveDecimals);
}
// NOT WORKING ON MATIC, DEPLOYING INDIVIDUAL IMPLs INSTEAD
// 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;
// Deploy stable and variable deployers and save implementations
const tx1 = await waitForTx(
await stableAndVariableDeployer.initDeployment(tokens, symbols, incentivesController)
);
tx1.events?.forEach((event, index) => {
rawInsertContractAddressInDb(`stableDebt${symbols[index]}`, event?.args?.stableToken);
rawInsertContractAddressInDb(`variableDebt${symbols[index]}`, event?.args?.variableToken);
});
const aTokenImplementation = await deployGenericATokenImpl(verify);
aTokenImplementationAddress = aTokenImplementation.address;
rawInsertContractAddressInDb(`aTokenImpl`, aTokenImplementationAddress);
// Deploy atokens and rate strategies and save implementations
const tx2 = await waitForTx(
await atokenAndRatesDeployer.initDeployment(
tokens,
symbols,
strategyRates,
treasuryAddress,
incentivesController
)
);
tx2.events?.forEach((event, index) => {
rawInsertContractAddressInDb(`a${symbols[index]}`, event?.args?.aToken);
rawInsertContractAddressInDb(`strategy${symbols[index]}`, event?.args?.strategy);
});
console.log(` - Deployed aToken, DebtTokens and Strategy for: ${symbols.join(', ')} `);
console.log(' * gasUsed: debtTokens batch', tx1.gasUsed.toString());
console.log(' * gasUsed: aTokens and Strategy batch', tx2.gasUsed.toString());
gasUsage = gasUsage.add(tx1.gasUsed).add(tx2.gasUsed);
const stableTokens: string[] = tx1.events?.map((e) => e.args?.stableToken) || [];
const variableTokens: string[] = tx1.events?.map((e) => e.args?.variableToken) || [];
const aTokens: string[] = tx2.events?.map((e) => e.args?.aToken) || [];
const strategies: string[] = tx2.events?.map((e) => e.args?.strategy) || [];
deployedStableTokens = [...deployedStableTokens, ...stableTokens];
deployedVariableTokens = [...deployedVariableTokens, ...variableTokens];
deployedATokens = [...deployedATokens, ...aTokens];
deployedRates = [...deployedRates, ...strategies];
reserveInitDecimals = [...reserveInitDecimals, ...reservesDecimals];
reserveTokens = [...reserveTokens, ...tokens];
reserveSymbols = [...reserveSymbols, ...symbols];
}
// Deploy delegated aware reserves tokens
const delegatedAwareReserves = Object.entries(reservesParams).filter(
([_, { aTokenImpl }]) => aTokenImpl === eContractid.DelegationAwareAToken
) as [string, IReserveParams][];
for (let [symbol, params] of delegatedAwareReserves) {
console.log(` - Deploy ${symbol} delegation aware aToken, debts tokens, and strategy`);
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) {
const { strategy, aTokenImpl, reserveDecimals } = params;
const {
optimalUtilizationRate,
baseVariableBorrowRate,
@ -187,89 +152,86 @@ export const initReservesByHelper = async (
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
} = params;
const deployCustomAToken = chooseATokenDeployment(params.aTokenImpl);
const aToken = await deployCustomAToken(
[
poolAddress,
tokenAddresses[symbol],
treasuryAddress,
`Aave interest bearing ${symbol}`,
`a${symbol}`,
ZERO_ADDRESS,
],
verify
);
const stableDebt = await deployStableDebtToken(
[
poolAddress,
tokenAddresses[symbol],
`Aave stable debt bearing ${symbol}`,
`stableDebt${symbol}`,
ZERO_ADDRESS,
],
verify
);
const variableDebt = await deployVariableDebtToken(
[
poolAddress,
tokenAddresses[symbol],
`Aave variable debt bearing ${symbol}`,
`variableDebt${symbol}`,
ZERO_ADDRESS,
],
verify
);
const rates = await deployDefaultReserveInterestRateStrategy(
[
tokenAddresses[symbol],
} = strategy;
if (!strategyAddresses[strategy.name]) {
// Strategy does not exist, create a new one
rateStrategies[strategy.name] = [
addressProvider.address,
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
],
verify
);
];
strategyAddresses[strategy.name] = (
await deployDefaultReserveInterestRateStrategy(rateStrategies[strategy.name], verify)
).address;
// This causes the last strategy to be printed twice, once under "DefaultReserveInterestRateStrategy"
// and once under the actual `strategyASSET` key.
rawInsertContractAddressInDb(strategy.name, strategyAddresses[strategy.name]);
}
strategyAddressPerAsset[symbol] = strategyAddresses[strategy.name];
console.log('Strategy address for asset %s: %s', symbol, strategyAddressPerAsset[symbol]);
deployedStableTokens.push(stableDebt.address);
deployedVariableTokens.push(variableDebt.address);
deployedATokens.push(aToken.address);
deployedRates.push(rates.address);
reserveInitDecimals.push(params.reserveDecimals);
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);
}
// Deploy init reserves per chunks
const chunkedStableTokens = chunk(deployedStableTokens, initChunks);
const chunkedVariableTokens = chunk(deployedVariableTokens, initChunks);
const chunkedAtokens = chunk(deployedATokens, initChunks);
const chunkedRates = chunk(deployedRates, initChunks);
const chunkedDecimals = chunk(reserveInitDecimals, initChunks);
const chunkedSymbols = chunk(reserveSymbols, initChunks);
for (let i = 0; i < reserveSymbols.length; i++) {
let aTokenToUse: string;
if (aTokenType[reserveSymbols[i]] === 'generic') {
aTokenToUse = aTokenImplementationAddress;
} else {
aTokenToUse = delegationAwareATokenImplementationAddress;
}
console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`);
for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) {
initInputParams.push({
aTokenImpl: aTokenToUse,
stableDebtTokenImpl: stableDebtTokenImplementationAddress,
variableDebtTokenImpl: variableDebtTokenImplementationAddress,
underlyingAssetDecimals: reserveInitDecimals[i],
interestRateStrategyAddress: strategyAddressPerAsset[reserveSymbols[i]],
underlyingAsset: reserveTokens[i],
treasury: treasuryAddress,
incentivesController: ZERO_ADDRESS,
underlyingAssetName: reserveSymbols[i],
aTokenName: `${aTokenNamePrefix} ${reserveSymbols[i]}`,
aTokenSymbol: `a${symbolPrefix}${reserveSymbols[i]}`,
variableDebtTokenName: `${variableDebtTokenNamePrefix} ${symbolPrefix}${reserveSymbols[i]}`,
variableDebtTokenSymbol: `variableDebt${symbolPrefix}${reserveSymbols[i]}`,
stableDebtTokenName: `${stableDebtTokenNamePrefix} ${reserveSymbols[i]}`,
stableDebtTokenSymbol: `stableDebt${symbolPrefix}${reserveSymbols[i]}`,
params: '0x10'
});
}
// Deploy init reserves per chunks
const chunkedSymbols = chunk(reserveSymbols, initChunks);
const chunkedInitInputParams = chunk(initInputParams, initChunks);
const configurator = await getLendingPoolConfiguratorProxy();
//await waitForTx(await addressProvider.setPoolAdmin(admin));
console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`);
for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) {
const tx3 = await waitForTx(
await atokenAndRatesDeployer.initReserve(
chunkedStableTokens[chunkIndex],
chunkedVariableTokens[chunkIndex],
chunkedAtokens[chunkIndex],
chunkedRates[chunkIndex],
chunkedDecimals[chunkIndex]
)
await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex])
);
console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`);
console.log(' * gasUsed', tx3.gasUsed.toString());
gasUsage = gasUsage.add(tx3.gasUsed);
//gasUsage = gasUsage.add(tx3.gasUsed);
}
// Set deployer back as admin
await waitForTx(await addressProvider.setPoolAdmin(admin));
return gasUsage;
return gasUsage; // Deprecated
};
export const getPairsTokenAggregator = (
@ -315,6 +277,15 @@ export const configureReservesByHelper = async (
const reserveFactors: string[] = [];
const stableRatesEnabled: boolean[] = [];
const inputParams: {
asset: string;
baseLTV: BigNumberish;
liquidationThreshold: BigNumberish;
liquidationBonus: BigNumberish;
reserveFactor: BigNumberish;
stableBorrowingEnabled: boolean;
}[] = [];
for (const [
assetSymbol,
{
@ -342,6 +313,16 @@ export const configureReservesByHelper = async (
continue;
}
// Push data
inputParams.push({
asset: tokenAddress,
baseLTV: baseLTVAsCollateral,
liquidationThreshold: liquidationThreshold,
liquidationBonus: liquidationBonus,
reserveFactor: reserveFactor,
stableBorrowingEnabled: stableBorrowRateEnabled,
});
tokens.push(tokenAddress);
symbols.push(assetSymbol);
baseLTVA.push(baseLTVAsCollateral);
@ -356,26 +337,15 @@ export const configureReservesByHelper = async (
// Deploy init per chunks
const enableChunks = 20;
const chunkedTokens = chunk(tokens, enableChunks);
const chunkedSymbols = chunk(symbols, enableChunks);
const chunkedBase = chunk(baseLTVA, enableChunks);
const chunkedliquidationThresholds = chunk(liquidationThresholds, enableChunks);
const chunkedliquidationBonuses = chunk(liquidationBonuses, enableChunks);
const chunkedReserveFactors = chunk(reserveFactors, enableChunks);
const chunkedStableRatesEnabled = chunk(stableRatesEnabled, enableChunks);
const chunkedInputParams = chunk(inputParams, enableChunks);
console.log(`- Configure reserves in ${chunkedTokens.length} txs`);
for (let chunkIndex = 0; chunkIndex < chunkedTokens.length; chunkIndex++) {
console.log(`- Configure reserves in ${chunkedInputParams.length} txs`);
for (let chunkIndex = 0; chunkIndex < chunkedInputParams.length; chunkIndex++) {
await waitForTx(
await atokenAndRatesDeployer.configureReserves(
chunkedTokens[chunkIndex],
chunkedBase[chunkIndex],
chunkedliquidationThresholds[chunkIndex],
chunkedliquidationBonuses[chunkIndex],
chunkedReserveFactors[chunkIndex],
chunkedStableRatesEnabled[chunkIndex],
{ gasLimit: 12000000 }
)
await atokenAndRatesDeployer.configureReserves(chunkedInputParams[chunkIndex], {
gasLimit: 12000000,
})
);
console.log(` - Init for: ${chunkedSymbols[chunkIndex].join(', ')}`);
}
@ -386,10 +356,13 @@ export const configureReservesByHelper = async (
const getAddressById = async (
id: string,
network: eEthereumNetwork
network: eNetwork
): Promise<tEthereumAddress | undefined> =>
(await getDb().get(`${id}.${network}`).value())?.address || undefined;
// Function deprecated? Updated but untested, script is not updated on package.json.
// This is not called during regular deployment, only in the "full:initialize-tokens"
// hardhat task.
export const initTokenReservesByHelper = async (
reservesParams: iMultiPoolsAssets<IReserveParams>,
tokenAddresses: { [symbol: string]: tEthereumAddress },
@ -415,7 +388,7 @@ export const initTokenReservesByHelper = async (
const poolAddress = await addressProvider.getLendingPool();
// Set aTokenAndRatesDeployer as temporal admin
await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address));
//await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address));
// CHUNK CONFIGURATION
const initChunks = 4;
@ -425,12 +398,31 @@ export const initTokenReservesByHelper = async (
let deployedVariableTokens: string[] = [];
let deployedATokens: string[] = [];
let deployedRates: string[] = [];
//let reserveTokens: string[] = [];
let reserveInitDecimals: string[] = [];
let reserveSymbols: string[] = [];
let initInputParams: {
aTokenImpl: string;
stableDebtTokenImpl: string;
variableDebtTokenImpl: string;
underlyingAssetDecimals: BigNumberish;
interestRateStrategyAddress: string;
underlyingAsset: string;
treasury: string;
incentivesController: string;
underlyingAssetName: string;
aTokenName: string;
aTokenSymbol: string;
variableDebtTokenName: string;
variableDebtTokenSymbol: string;
stableDebtTokenName: string;
stableDebtTokenSymbol: string;
params: string;
}[] = [];
const network =
process.env.MAINNET_FORK === 'true'
? eEthereumNetwork.main
: (DRE.network.name as eEthereumNetwork);
process.env.MAINNET_FORK === 'true' ? eEthereumNetwork.main : (DRE.network.name as eNetwork);
// Grab config from DB
for (const [symbol, address] of Object.entries(tokenAddresses)) {
const { aTokenAddress } = await protocolDataProvider.getReserveTokensAddresses(address);
@ -444,19 +436,29 @@ export const initTokenReservesByHelper = async (
console.log(`- Skipping ${symbol} due already initialized`);
continue;
}
let stableTokenImpl = await getAddressById(`stableDebt${symbol}`, network);
let variableTokenImpl = await getAddressById(`variableDebt${symbol}`, network);
let aTokenImplementation = await getAddressById(`a${symbol}`, network);
let strategyImpl = await getAddressById(`strategy${symbol}`, network);
let stableTokenImpl = await getAddressById(`stableDebtTokenImpl`, network);
let variableTokenImpl = await getAddressById(`variableDebtTokenImpl`, network);
let aTokenImplementation: string | undefined = '';
const [, { aTokenImpl, strategy }] = (Object.entries(reservesParams) as [
string,
IReserveParams
][])[reserveParamIndex];
if (aTokenImpl === eContractid.AToken) {
aTokenImplementation = await getAddressById(`aTokenImpl`, network);
} else if (aTokenImpl === eContractid.DelegationAwareAToken) {
aTokenImplementation = await getAddressById(`delegationAwareATokenImpl`, network);
}
let strategyImpl = await getAddressById(strategy.name, network);
if (!stableTokenImpl) {
const stableDebt = await deployStableDebtToken(
[
poolAddress,
tokenAddresses[symbol],
ZERO_ADDRESS, // Incentives controller
`Aave stable debt bearing ${symbol}`,
`stableDebt${symbol}`,
ZERO_ADDRESS,
],
verify
);
@ -467,9 +469,9 @@ export const initTokenReservesByHelper = async (
[
poolAddress,
tokenAddresses[symbol],
ZERO_ADDRESS, // Incentives Controller
`Aave variable debt bearing ${symbol}`,
`variableDebt${symbol}`,
ZERO_ADDRESS,
],
verify
);
@ -485,26 +487,26 @@ export const initTokenReservesByHelper = async (
poolAddress,
tokenAddresses[symbol],
treasuryAddress,
ZERO_ADDRESS,
`Aave interest bearing ${symbol}`,
`a${symbol}`,
ZERO_ADDRESS,
],
verify
);
aTokenImplementation = aToken.address;
}
if (!strategyImpl) {
const [
,
{
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
},
] = (Object.entries(reservesParams) as [string, IReserveParams][])[reserveParamIndex];
const [, { strategy }] = (Object.entries(reservesParams) as [string, IReserveParams][])[
reserveParamIndex
];
const {
optimalUtilizationRate,
baseVariableBorrowRate,
variableRateSlope1,
variableRateSlope2,
stableRateSlope1,
stableRateSlope2,
} = strategy;
const rates = await deployDefaultReserveInterestRateStrategy(
[
tokenAddresses[symbol],
@ -519,53 +521,69 @@ export const initTokenReservesByHelper = async (
);
strategyImpl = rates.address;
}
const symbols = [`a${symbol}`, `variableDebt${symbol}`, `stableDebt${symbol}`];
const tokens = [aTokenImplementation, variableTokenImpl, stableTokenImpl];
for (let index = 0; index < symbols.length; index++) {
if (!(await isErc20SymbolCorrect(tokens[index], symbols[index]))) {
console.error(`${symbol} and implementation does not match: ${tokens[index]}`);
throw Error('Symbol does not match implementation.');
}
}
// --- REMOVED BECAUSE WE NOW USE THE SAME IMPLEMENTATIONS ---
// const symbols = [`a${symbol}`, `variableDebt${symbol}`, `stableDebt${symbol}`];
// const tokens = [aTokenImplementation, variableTokenImpl, stableTokenImpl];
// for (let index = 0; index < symbols.length; index++) {
// if (!(await isErc20SymbolCorrect(tokens[index], symbols[index]))) {
// console.error(`${symbol} and implementation does not match: ${tokens[index]}`);
// throw Error('Symbol does not match implementation.');
// }
// }
console.log(`- Added ${symbol} to the initialize batch`);
deployedStableTokens.push(stableTokenImpl);
deployedVariableTokens.push(variableTokenImpl);
deployedATokens.push(aTokenImplementation);
//reserveTokens.push();
deployedRates.push(strategyImpl);
reserveInitDecimals.push(decimals.toString());
reserveSymbols.push(symbol);
}
// Deploy init reserves per chunks
const chunkedStableTokens = chunk(deployedStableTokens, initChunks);
const chunkedVariableTokens = chunk(deployedVariableTokens, initChunks);
const chunkedAtokens = chunk(deployedATokens, initChunks);
const chunkedRates = chunk(deployedRates, initChunks);
const chunkedDecimals = chunk(reserveInitDecimals, initChunks);
const chunkedSymbols = chunk(reserveSymbols, initChunks);
for (let i = 0; i < deployedATokens.length; i++) {
initInputParams.push({
aTokenImpl: deployedATokens[i],
stableDebtTokenImpl: deployedStableTokens[i],
variableDebtTokenImpl: deployedVariableTokens[i],
underlyingAssetDecimals: reserveInitDecimals[i],
interestRateStrategyAddress: deployedRates[i],
underlyingAsset: tokenAddresses[reserveSymbols[i]],
treasury: treasuryAddress,
incentivesController: ZERO_ADDRESS,
underlyingAssetName: reserveSymbols[i],
aTokenName: `Aave interest bearing ${reserveSymbols[i]}`,
aTokenSymbol: `a${reserveSymbols[i]}`,
variableDebtTokenName: `Aave variable debt bearing ${reserveSymbols[i]}`,
variableDebtTokenSymbol: `variableDebt${reserveSymbols[i]}`,
stableDebtTokenName: `Aave stable debt bearing ${reserveSymbols[i]}`,
stableDebtTokenSymbol: `stableDebt${reserveSymbols[i]}`,
params: '0x10'
});
}
console.log(`- Reserves initialization in ${chunkedStableTokens.length} txs`);
for (let chunkIndex = 0; chunkIndex < chunkedDecimals.length; chunkIndex++) {
// Deploy init reserves per chunks
const chunkedSymbols = chunk(reserveSymbols, initChunks);
const chunkedInitInputParams = chunk(initInputParams, initChunks);
const configurator = await getLendingPoolConfiguratorProxy();
//await waitForTx(await addressProvider.setPoolAdmin(admin));
console.log(`- Reserves initialization in ${chunkedInitInputParams.length} txs`);
for (let chunkIndex = 0; chunkIndex < chunkedInitInputParams.length; chunkIndex++) {
const tx3 = await waitForTx(
await atokenAndRatesDeployer.initReserve(
chunkedStableTokens[chunkIndex],
chunkedVariableTokens[chunkIndex],
chunkedAtokens[chunkIndex],
chunkedRates[chunkIndex],
chunkedDecimals[chunkIndex]
)
await configurator.batchInitReserve(chunkedInitInputParams[chunkIndex])
);
console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`);
console.log(' * gasUsed', tx3.gasUsed.toString());
gasUsage = gasUsage.add(tx3.gasUsed);
}
// Set deployer back as admin
await waitForTx(await addressProvider.setPoolAdmin(admin));
return gasUsage;
//await waitForTx(await addressProvider.setPoolAdmin(admin));
return gasUsage; // No longer relevant
};
// Function deprecated
const isErc20SymbolCorrect = async (token: tEthereumAddress, symbol: string) => {
const erc20 = await getAToken(token); // using aToken for ERC20 interface
const erc20Symbol = await erc20.symbol();

View File

@ -2,13 +2,13 @@ import BigNumber from 'bignumber.js';
import BN = require('bn.js');
import low from 'lowdb';
import FileSync from 'lowdb/adapters/FileSync';
import {WAD} from './constants';
import {Wallet, ContractTransaction} from 'ethers';
import {HardhatRuntimeEnvironment} from 'hardhat/types';
import {BuidlerRuntimeEnvironment} from '@nomiclabs/buidler/types';
import {tEthereumAddress} from './types';
import {isAddress} from 'ethers/lib/utils';
import {isZeroAddress} from 'ethereumjs-util';
import { WAD } from './constants';
import { Wallet, ContractTransaction } from 'ethers';
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { BuidlerRuntimeEnvironment } from '@nomiclabs/buidler/types';
import { tEthereumAddress } from './types';
import { isAddress } from 'ethers/lib/utils';
import { isZeroAddress } from 'ethereumjs-util';
export const toWad = (value: string | number) => new BigNumber(value).times(WAD).toFixed();
@ -17,9 +17,8 @@ export const stringToBigNumber = (amount: string): BigNumber => new BigNumber(am
export const getDb = () => low(new FileSync('./deployed-contracts.json'));
export let DRE:
| HardhatRuntimeEnvironment
| BuidlerRuntimeEnvironment = {} as HardhatRuntimeEnvironment;
export let DRE: HardhatRuntimeEnvironment | BuidlerRuntimeEnvironment;
export const setDRE = (_DRE: HardhatRuntimeEnvironment | BuidlerRuntimeEnvironment) => {
DRE = _DRE;
};
@ -47,12 +46,32 @@ export const increaseTime = async (secondsToIncrease: number) => {
await DRE.ethers.provider.send('evm_mine', []);
};
// Workaround for time travel tests bug: https://github.com/Tonyhaenn/hh-time-travel/blob/0161d993065a0b7585ec5a043af2eb4b654498b8/test/test.js#L12
export const advanceTimeAndBlock = async function (forwardTime: number) {
const currentBlockNumber = await DRE.ethers.provider.getBlockNumber();
const currentBlock = await DRE.ethers.provider.getBlock(currentBlockNumber);
if (currentBlock === null) {
/* Workaround for https://github.com/nomiclabs/hardhat/issues/1183
*/
await DRE.ethers.provider.send('evm_increaseTime', [forwardTime]);
await DRE.ethers.provider.send('evm_mine', []);
//Set the next blocktime back to 15 seconds
await DRE.ethers.provider.send('evm_increaseTime', [15]);
return;
}
const currentTime = currentBlock.timestamp;
const futureTime = currentTime + forwardTime;
await DRE.ethers.provider.send('evm_setNextBlockTimestamp', [futureTime]);
await DRE.ethers.provider.send('evm_mine', []);
};
export const waitForTx = async (tx: ContractTransaction) => await tx.wait(1);
export const filterMapBy = (raw: {[key: string]: any}, fn: (key: string) => boolean) =>
export const filterMapBy = (raw: { [key: string]: any }, fn: (key: string) => boolean) =>
Object.keys(raw)
.filter(fn)
.reduce<{[key: string]: any}>((obj, key) => {
.reduce<{ [key: string]: any }>((obj, key) => {
obj[key] = raw[key];
return obj;
}, {});

View File

@ -1,10 +1,10 @@
import {tEthereumAddress} from './types';
import {MockAggregator} from '../types/MockAggregator';
import {MockTokenMap} from './contracts-helpers';
import { tEthereumAddress } from './types';
import { MockAggregator } from '../types/MockAggregator';
import { MockTokenMap } from './contracts-helpers';
export const getAllTokenAddresses = (mockTokens: MockTokenMap) =>
Object.entries(mockTokens).reduce(
(accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, tokenContract]) => ({
(accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, tokenContract]) => ({
...accum,
[tokenSymbol]: tokenContract.address,
}),
@ -14,7 +14,7 @@ export const getAllAggregatorsAddresses = (mockAggregators: {
[tokenSymbol: string]: MockAggregator;
}) =>
Object.entries(mockAggregators).reduce(
(accum: {[tokenSymbol: string]: tEthereumAddress}, [tokenSymbol, aggregator]) => ({
(accum: { [tokenSymbol: string]: tEthereumAddress }, [tokenSymbol, aggregator]) => ({
...accum,
[tokenSymbol]: aggregator.address,
}),

View File

@ -7,16 +7,16 @@ import {
SymbolMap,
} from './types';
import {LendingRateOracle} from '../types/LendingRateOracle';
import {PriceOracle} from '../types/PriceOracle';
import {MockAggregator} from '../types/MockAggregator';
import {deployMockAggregator} from './contracts-deployments';
import {chunk, waitForTx} from './misc-utils';
import {getStableAndVariableTokensHelper} from './contracts-getters';
import { LendingRateOracle } from '../types/LendingRateOracle';
import { PriceOracle } from '../types/PriceOracle';
import { MockAggregator } from '../types/MockAggregator';
import { deployMockAggregator } from './contracts-deployments';
import { chunk, waitForTx } from './misc-utils';
import { getStableAndVariableTokensHelper } from './contracts-getters';
export const setInitialMarketRatesInRatesOracleByHelper = async (
marketRates: iMultiPoolsAssets<IMarketRates>,
assetsAddresses: {[x: string]: tEthereumAddress},
assetsAddresses: { [x: string]: tEthereumAddress },
lendingRateOracleInstance: LendingRateOracle,
admin: tEthereumAddress
) => {
@ -24,7 +24,7 @@ export const setInitialMarketRatesInRatesOracleByHelper = async (
const assetAddresses: string[] = [];
const borrowRates: string[] = [];
const symbols: string[] = [];
for (const [assetSymbol, {borrowRate}] of Object.entries(marketRates) as [
for (const [assetSymbol, { borrowRate }] of Object.entries(marketRates) as [
string,
IMarketRates
][]) {
@ -72,6 +72,9 @@ export const setInitialAssetPricesInOracle = async (
priceOracleInstance: PriceOracle
) => {
for (const [assetSymbol, price] of Object.entries(prices) as [string, string][]) {
console.log("Trying for ", assetsAddresses, assetSymbol);
const assetAddressIndex = Object.keys(assetsAddresses).findIndex(
(value) => value === assetSymbol
);
@ -99,7 +102,7 @@ export const setAssetPricesInOracle = async (
};
export const deployMockAggregators = async (initialPrices: SymbolMap<string>, verify?: boolean) => {
const aggregators: {[tokenSymbol: string]: MockAggregator} = {};
const aggregators: { [tokenSymbol: string]: MockAggregator } = {};
for (const tokenContractName of Object.keys(initialPrices)) {
if (tokenContractName !== 'ETH') {
const priceIndex = Object.keys(initialPrices).findIndex(
@ -116,7 +119,7 @@ export const deployAllMockAggregators = async (
initialPrices: iAssetAggregatorBase<string>,
verify?: boolean
) => {
const aggregators: {[tokenSymbol: string]: MockAggregator} = {};
const aggregators: { [tokenSymbol: string]: MockAggregator } = {};
for (const tokenContractName of Object.keys(initialPrices)) {
if (tokenContractName !== 'ETH') {
const priceIndex = Object.keys(initialPrices).findIndex(

View File

@ -0,0 +1,7 @@
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { DRE } from './misc-utils';
export const usingTenderly = () =>
DRE &&
((DRE as HardhatRuntimeEnvironment).network.name.includes('tenderly') ||
process.env.TENDERLY === 'true');

View File

@ -4,6 +4,8 @@ export interface SymbolMap<T> {
[symbol: string]: T;
}
export type eNetwork = eEthereumNetwork | ePolygonNetwork | eXDaiNetwork;
export enum eEthereumNetwork {
buidlerevm = 'buidlerevm',
kovan = 'kovan',
@ -14,14 +16,28 @@ export enum eEthereumNetwork {
tenderlyMain = 'tenderlyMain',
}
export enum ePolygonNetwork {
matic = 'matic',
mumbai = 'mumbai',
}
export enum eXDaiNetwork {
xdai = 'xdai',
}
export enum EthereumNetworkNames {
kovan = 'kovan',
ropsten = 'ropsten',
main = 'main',
matic = 'matic',
mumbai = 'mumbai',
xdai = 'xdai',
}
export enum AavePools {
proto = 'proto',
matic = 'matic',
amm = 'amm',
}
export enum eContractid {
@ -70,6 +86,7 @@ export enum eContractid {
MockUniswapV2Router02 = 'MockUniswapV2Router02',
UniswapLiquiditySwapAdapter = 'UniswapLiquiditySwapAdapter',
UniswapRepayAdapter = 'UniswapRepayAdapter',
FlashLiquidationAdapter = 'FlashLiquidationAdapter',
}
/*
@ -203,6 +220,25 @@ export interface iAssetBase<T> {
USD: T;
REN: T;
ENJ: T;
UniDAIWETH: T;
UniWBTCWETH: T;
UniAAVEWETH: T;
UniBATWETH: T;
UniDAIUSDC: T;
UniCRVWETH: T;
UniLINKWETH: T;
UniMKRWETH: T;
UniRENWETH: T;
UniSNXWETH: T;
UniUNIWETH: T;
UniUSDCWETH: T;
UniWBTCUSDC: T;
UniYFIWETH: T;
BptWBTCWETH: T;
BptBALWETH: T;
WMATIC: T;
STAKE: T;
xSUSHI: T;
}
export type iAssetsWithoutETH<T> = Omit<iAssetBase<T>, 'ETH'>;
@ -231,6 +267,42 @@ export type iAavePoolAssets<T> = Pick<
| 'UNI'
| 'REN'
| 'ENJ'
| 'xSUSHI'
>;
export type iLpPoolAssets<T> = Pick<
iAssetsWithoutUSD<T>,
| 'DAI'
| 'USDC'
| 'USDT'
| 'WBTC'
| 'WETH'
| 'UniDAIWETH'
| 'UniWBTCWETH'
| 'UniAAVEWETH'
| 'UniBATWETH'
| 'UniDAIUSDC'
| 'UniCRVWETH'
| 'UniLINKWETH'
| 'UniMKRWETH'
| 'UniRENWETH'
| 'UniSNXWETH'
| 'UniUNIWETH'
| 'UniUSDCWETH'
| 'UniWBTCUSDC'
| 'UniYFIWETH'
| 'BptWBTCWETH'
| 'BptBALWETH'
>;
export type iMaticPoolAssets<T> = Pick<
iAssetsWithoutUSD<T>,
'DAI' | 'USDC' | 'USDT' | 'WBTC' | 'WETH' | 'WMATIC'
>;
export type iXDAIPoolAssets<T> = Pick<
iAssetsWithoutUSD<T>,
'DAI' | 'USDC' | 'USDT' | 'WBTC' | 'WETH' | 'STAKE'
>;
export type iMultiPoolsAssets<T> = iAssetCommon<T> | iAavePoolAssets<T>;
@ -261,20 +333,50 @@ export enum TokenContractId {
YFI = 'YFI',
UNI = 'UNI',
ENJ = 'ENJ',
UniDAIWETH = 'UniDAIWETH',
UniWBTCWETH = 'UniWBTCWETH',
UniAAVEWETH = 'UniAAVEWETH',
UniBATWETH = 'UniBATWETH',
UniDAIUSDC = 'UniDAIUSDC',
UniCRVWETH = 'UniCRVWETH',
UniLINKWETH = 'UniLINKWETH',
UniMKRWETH = 'UniMKRWETH',
UniRENWETH = 'UniRENWETH',
UniSNXWETH = 'UniSNXWETH',
UniUNIWETH = 'UniUNIWETH',
UniUSDCWETH = 'UniUSDCWETH',
UniWBTCUSDC = 'UniWBTCUSDC',
UniYFIWETH = 'UniYFIWETH',
BptWBTCWETH = 'BptWBTCWETH',
BptBALWETH = 'BptBALWETH',
WMATIC = 'WMATIC',
STAKE = 'STAKE',
xSUSHI = 'xSUSHI'
}
export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams {
aTokenImpl: eContractid;
reserveFactor: string;
strategy: IInterestRateStrategyParams;
}
export interface IReserveBorrowParams {
export interface IInterestRateStrategyParams {
name: string;
optimalUtilizationRate: string;
baseVariableBorrowRate: string;
variableRateSlope1: string;
variableRateSlope2: string;
stableRateSlope1: string;
stableRateSlope2: string;
}
export interface IReserveBorrowParams {
// optimalUtilizationRate: string;
// baseVariableBorrowRate: string;
// variableRateSlope1: string;
// variableRateSlope2: string;
// stableRateSlope1: string;
// stableRateSlope2: string;
borrowingEnabled: boolean;
stableBorrowRateEnabled: boolean;
reserveDecimals: string;
@ -289,7 +391,17 @@ export interface IMarketRates {
borrowRate: string;
}
export interface iParamsPerNetwork<T> {
export type iParamsPerNetwork<T> =
| iEthereumParamsPerNetwork<T>
| iPolygonParamsPerNetwork<T>
| iXDaiParamsPerNetwork<T>;
export interface iParamsPerNetworkAll<T>
extends iEthereumParamsPerNetwork<T>,
iPolygonParamsPerNetwork<T>,
iXDaiParamsPerNetwork<T> {}
export interface iEthereumParamsPerNetwork<T> {
[eEthereumNetwork.coverage]: T;
[eEthereumNetwork.buidlerevm]: T;
[eEthereumNetwork.kovan]: T;
@ -299,8 +411,19 @@ export interface iParamsPerNetwork<T> {
[eEthereumNetwork.tenderlyMain]: T;
}
export interface iPolygonParamsPerNetwork<T> {
[ePolygonNetwork.matic]: T;
[ePolygonNetwork.mumbai]: T;
}
export interface iXDaiParamsPerNetwork<T> {
[eXDaiNetwork.xdai]: T;
}
export interface iParamsPerPool<T> {
[AavePools.proto]: T;
[AavePools.matic]: T;
[AavePools.amm]: T;
}
export interface iBasicDistributionParams {
@ -318,15 +441,6 @@ export interface ObjectString {
[key: string]: string;
}
export enum EthereumNetwork {
kovan = 'kovan',
ropsten = 'ropsten',
development = 'development',
main = 'main',
coverage = 'soliditycoverage',
tenderlyMain = 'tenderlyMain',
}
export interface IProtocolGlobalConfig {
TokenDistributorPercentageBase: string;
MockUsdPriceInWei: string;
@ -350,11 +464,18 @@ export interface ILendingRate {
export interface ICommonConfiguration {
MarketId: string;
ATokenNamePrefix: string;
StableDebtTokenNamePrefix: string;
VariableDebtTokenNamePrefix: string;
SymbolPrefix: string;
ProviderId: number;
ProtocolGlobalParams: IProtocolGlobalConfig;
Mocks: IMocksConfig;
ProviderRegistry: iParamsPerNetwork<tEthereumAddress | undefined>;
ProviderRegistryOwner: iParamsPerNetwork<tEthereumAddress | undefined>;
LendingPoolCollateralManager: iParamsPerNetwork<tEthereumAddress>;
LendingPoolConfigurator: iParamsPerNetwork<tEthereumAddress>;
LendingPool: iParamsPerNetwork<tEthereumAddress>;
LendingRateOracleRatesCommon: iMultiPoolsAssets<IMarketRates>;
LendingRateOracle: iParamsPerNetwork<tEthereumAddress>;
TokenDistributor: iParamsPerNetwork<tEthereumAddress>;
@ -369,12 +490,26 @@ export interface ICommonConfiguration {
ReservesConfig: iMultiPoolsAssets<IReserveParams>;
ATokenDomainSeparator: iParamsPerNetwork<string>;
WETH: iParamsPerNetwork<tEthereumAddress>;
WethGateway: iParamsPerNetwork<tEthereumAddress>;
ReserveFactorTreasuryAddress: iParamsPerNetwork<tEthereumAddress>;
}
export interface IAaveConfiguration extends ICommonConfiguration {
ReservesConfig: iAavePoolAssets<IReserveParams>;
}
export interface IAmmConfiguration extends ICommonConfiguration {
ReservesConfig: iLpPoolAssets<IReserveParams>;
}
export interface IMaticConfiguration extends ICommonConfiguration {
ReservesConfig: iMaticPoolAssets<IReserveParams>;
}
export interface IXDAIConfiguration extends ICommonConfiguration {
ReservesConfig: iXDAIPoolAssets<IReserveParams>;
}
export interface ITokenAddress {
[token: string]: tEthereumAddress;
}

View File

@ -1,37 +1,18 @@
import BigNumber from 'bignumber.js';
import { oneEther, oneRay, RAY, ZERO_ADDRESS } from '../../helpers/constants';
import { ICommonConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types';
import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants';
import { ICommonConfiguration, eEthereumNetwork } from '../../helpers/types';
const MOCK_CHAINLINK_AGGREGATORS_PRICES = {
AAVE: oneEther.multipliedBy('0.003620948469').toFixed(),
BAT: oneEther.multipliedBy('0.00137893825230').toFixed(),
BUSD: oneEther.multipliedBy('0.00736484').toFixed(),
DAI: oneEther.multipliedBy('0.00369068412860').toFixed(),
ENJ: oneEther.multipliedBy('0.00029560').toFixed(),
KNC: oneEther.multipliedBy('0.001072').toFixed(),
LINK: oneEther.multipliedBy('0.009955').toFixed(),
MANA: oneEther.multipliedBy('0.000158').toFixed(),
MKR: oneEther.multipliedBy('2.508581').toFixed(),
REN: oneEther.multipliedBy('0.00065133').toFixed(),
SNX: oneEther.multipliedBy('0.00442616').toFixed(),
SUSD: oneEther.multipliedBy('0.00364714136416').toFixed(),
TUSD: oneEther.multipliedBy('0.00364714136416').toFixed(),
UNI: oneEther.multipliedBy('0.00536479').toFixed(),
USDC: oneEther.multipliedBy('0.00367714136416').toFixed(),
USDT: oneEther.multipliedBy('0.00369068412860').toFixed(),
WETH: oneEther.toFixed(),
WBTC: oneEther.multipliedBy('47.332685').toFixed(),
YFI: oneEther.multipliedBy('22.407436').toFixed(),
ZRX: oneEther.multipliedBy('0.001151').toFixed(),
USD: '5848466240000000',
};
// ----------------
// PROTOCOL GLOBAL PARAMS
// ----------------
export const CommonsConfig: ICommonConfiguration = {
MarketId: 'Commons',
ProviderId: 0,
ATokenNamePrefix: 'Aave interest bearing',
StableDebtTokenNamePrefix: 'Aave stable debt bearing',
VariableDebtTokenNamePrefix: 'Aave variable debt bearing',
SymbolPrefix: '',
ProviderId: 0, // Overriden in index.ts
ProtocolGlobalParams: {
TokenDistributorPercentageBase: '10000',
MockUsdPriceInWei: '5848466240000000',
@ -158,43 +139,79 @@ export const CommonsConfig: ICommonConfiguration = {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a',
[eEthereumNetwork.kovan]: '',//'0xdCde9Bb6a49e37fA433990832AB541AE2d4FEB4a',
[eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b',
[eEthereumNetwork.main]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D',
[eEthereumNetwork.main]: '',//'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D',
[eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D',
},
LendingPoolCollateralManager: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0x9269b6453d0d75370c4c85e5a42977a53efdb72a',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C',
[eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C',
},
LendingPoolConfigurator: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '',
[eEthereumNetwork.tenderlyMain]: '',
},
LendingPool: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '',
[eEthereumNetwork.tenderlyMain]: '',
},
WethGateway: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0xf99b8E67a0E044734B01EC4586D1c88C9a869718',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '',
[eEthereumNetwork.tenderlyMain]: '',
},
TokenDistributor: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.hardhat]: '',
[EthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708',
[EthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c',
[EthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae',
[EthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae',
[eEthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708',
[eEthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c',
[eEthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae',
[eEthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae',
},
AaveOracle: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[EthereumNetwork.kovan]: '0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1',
[EthereumNetwork.ropsten]: ZERO_ADDRESS,
[EthereumNetwork.main]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9',
[EthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9',
[eEthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1',
[eEthereumNetwork.ropsten]: ZERO_ADDRESS,
[eEthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9',
[eEthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9',
},
FallbackOracle: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[EthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe',
[EthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d',
[EthereumNetwork.main]: ZERO_ADDRESS,
[EthereumNetwork.tenderlyMain]: ZERO_ADDRESS,
[eEthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe',
[eEthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d',
[eEthereumNetwork.main]: ZERO_ADDRESS,
[eEthereumNetwork.tenderlyMain]: ZERO_ADDRESS,
},
ChainlinkAggregator: {
[eEthereumNetwork.coverage]: {},
[eEthereumNetwork.hardhat]: {},
[eEthereumNetwork.buidlerevm]: {},
[EthereumNetwork.kovan]: {
[eEthereumNetwork.kovan]: {
AAVE: '0xd04647B7CB523bb9f26730E9B6dE1174db7591Ad',
BAT: '0x0e4fcEC26c9f85c3D714370c98f43C4E02Fc35Ae',
BUSD: '0xbF7A18ea5DE0501f7559144e702b29c55b055CcB',
@ -216,7 +233,7 @@ export const CommonsConfig: ICommonConfiguration = {
ZRX: '0xBc3f28Ccc21E9b5856E81E6372aFf57307E2E883',
USD: '0x9326BFA02ADD2366b30bacB125260Af641031331',
},
[EthereumNetwork.ropsten]: {
[eEthereumNetwork.ropsten]: {
AAVE: ZERO_ADDRESS,
BAT: '0xafd8186c962daf599f171b8600f3e19af7b52c92',
BUSD: '0x0A32D96Ff131cd5c3E0E5AAB645BF009Eda61564',
@ -238,7 +255,7 @@ export const CommonsConfig: ICommonConfiguration = {
ZRX: '0x1d0052e4ae5b4ae4563cbac50edc3627ca0460d7',
USD: '0x8468b2bDCE073A157E560AA4D9CcF6dB1DB98507',
},
[EthereumNetwork.main]: {
[eEthereumNetwork.main]: {
AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012',
BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94',
BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd',
@ -260,7 +277,7 @@ export const CommonsConfig: ICommonConfiguration = {
ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962',
USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419',
},
[EthereumNetwork.tenderlyMain]: {
[eEthereumNetwork.tenderlyMain]: {
AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012',
BAT: '0x0d16d4528239e9ee52fa531af613AcdB23D88c94',
BUSD: '0x614715d2Af89E6EC99A233818275142cE88d1Cfd',
@ -287,10 +304,10 @@ export const CommonsConfig: ICommonConfiguration = {
[eEthereumNetwork.coverage]: {},
[eEthereumNetwork.hardhat]: {},
[eEthereumNetwork.buidlerevm]: {},
[EthereumNetwork.main]: {},
[EthereumNetwork.kovan]: {},
[EthereumNetwork.ropsten]: {},
[EthereumNetwork.tenderlyMain]: {},
[eEthereumNetwork.main]: {},
[eEthereumNetwork.kovan]: {},
[eEthereumNetwork.ropsten]: {},
[eEthereumNetwork.tenderlyMain]: {},
},
ReservesConfig: {},
ATokenDomainSeparator: {

View File

@ -1,5 +1,5 @@
import { oneRay, ZERO_ADDRESS } from '../../helpers/constants';
import { IAaveConfiguration, EthereumNetwork, eEthereumNetwork } from '../../helpers/types';
import { IAaveConfiguration, eEthereumNetwork } from '../../helpers/types';
import { CommonsConfig } from './commons';
import {
@ -22,6 +22,7 @@ import {
strategyWBTC,
strategyWETH,
strategyYFI,
strategyXSUSHI,
} from './reservesConfigs';
// ----------------
@ -53,12 +54,13 @@ export const AaveConfig: IAaveConfiguration = {
WETH: strategyWETH,
YFI: strategyYFI,
ZRX: strategyZRX,
xSUSHI: strategyXSUSHI,
},
ReserveAssets: {
[eEthereumNetwork.buidlerevm]: {},
[eEthereumNetwork.hardhat]: {},
[eEthereumNetwork.coverage]: {},
[EthereumNetwork.kovan]: {
[eEthereumNetwork.kovan]: {
AAVE: '0xB597cd8D3217ea6477232F9217fa70837ff667Af',
BAT: '0x2d12186Fbb9f9a8C28B3FfdD4c42920f8539D738',
BUSD: '0x4c6E1EFC12FDfD568186b7BAEc0A43fFfb4bCcCf',
@ -80,7 +82,7 @@ export const AaveConfig: IAaveConfiguration = {
YFI: '0xb7c325266ec274fEb1354021D27FA3E3379D840d',
ZRX: '0xD0d76886cF8D952ca26177EB7CfDf83bad08C00C',
},
[EthereumNetwork.ropsten]: {
[eEthereumNetwork.ropsten]: {
AAVE: '',
BAT: '0x85B24b3517E3aC7bf72a14516160541A60cFF19d',
BUSD: '0xFA6adcFf6A90c11f31Bc9bb59eC0a6efB38381C6',
@ -102,7 +104,7 @@ export const AaveConfig: IAaveConfiguration = {
YFI: ZERO_ADDRESS,
ZRX: '0x02d7055704EfF050323A2E5ee4ba05DB2A588959',
},
[EthereumNetwork.main]: {
[eEthereumNetwork.main]: {
AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9',
BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef',
BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53',
@ -123,8 +125,9 @@ export const AaveConfig: IAaveConfiguration = {
WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e',
ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498',
xSUSHI: '0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272',
},
[EthereumNetwork.tenderlyMain]: {
[eEthereumNetwork.tenderlyMain]: {
AAVE: '0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9',
BAT: '0x0d8775f648430679a709e98d2b0cb6250d2887ef',
BUSD: '0x4Fabb145d64652a948d72533023f6E7A623C7C53',
@ -145,6 +148,7 @@ export const AaveConfig: IAaveConfiguration = {
WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
YFI: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e',
ZRX: '0xE41d2489571d322189246DaFA5ebDe1F4699F498',
xSUSHI: '0x8798249c2E607446EfB7Ad49eC89dD1865Ff4272',
},
},
};

View File

@ -0,0 +1,105 @@
import BigNumber from 'bignumber.js';
import { oneRay } from '../../helpers/constants';
import { IInterestRateStrategyParams } from '../../helpers/types';
// BUSD SUSD
export const rateStrategyStableOne: IInterestRateStrategyParams = {
name: "rateStrategyStableOne",
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
};
// DAI TUSD
export const rateStrategyStableTwo: IInterestRateStrategyParams = {
name: "rateStrategyStableTwo",
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
}
// USDC USDT
export const rateStrategyStableThree: IInterestRateStrategyParams = {
name: "rateStrategyStableThree",
optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
}
// WETH
export const rateStrategyWETH: IInterestRateStrategyParams = {
name: "rateStrategyWETH",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
}
// AAVE
export const rateStrategyAAVE: IInterestRateStrategyParams = {
name: "rateStrategyAAVE",
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: '0',
variableRateSlope2: '0',
stableRateSlope1: '0',
stableRateSlope2: '0',
}
// BAT ENJ LINK MANA MKR REN YFI ZRX
export const rateStrategyVolatileOne: IInterestRateStrategyParams = {
name: "rateStrategyVolatileOne",
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}
// KNC WBTC
export const rateStrategyVolatileTwo: IInterestRateStrategyParams = {
name: "rateStrategyVolatileTwo",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}
// SNX
export const rateStrategyVolatileThree: IInterestRateStrategyParams = {
name: "rateStrategyVolatileThree",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}
export const rateStrategyVolatileFour: IInterestRateStrategyParams = {
name: "rateStrategyVolatileFour",
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
}

View File

@ -1,14 +1,19 @@
import BigNumber from 'bignumber.js';
import { oneRay } from '../../helpers/constants';
import { eContractid, IReserveParams } from '../../helpers/types';
import {
rateStrategyStableOne,
rateStrategyStableTwo,
rateStrategyStableThree,
rateStrategyWETH,
rateStrategyAAVE,
rateStrategyVolatileOne,
rateStrategyVolatileTwo,
rateStrategyVolatileThree,
rateStrategyVolatileFour,
} from './rateStrategies';
export const strategyBUSD: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
strategy: rateStrategyStableOne,
baseLTVAsCollateral: '0',
liquidationThreshold: '0',
liquidationBonus: '0',
@ -20,12 +25,7 @@ export const strategyBUSD: IReserveParams = {
};
export const strategyDAI: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyStableTwo,
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
@ -37,12 +37,7 @@ export const strategyDAI: IReserveParams = {
};
export const strategySUSD: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
strategy: rateStrategyStableOne,
baseLTVAsCollateral: '0',
liquidationThreshold: '0',
liquidationBonus: '0',
@ -54,12 +49,7 @@ export const strategySUSD: IReserveParams = {
};
export const strategyTUSD: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyStableTwo,
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
@ -71,12 +61,7 @@ export const strategyTUSD: IReserveParams = {
};
export const strategyUSDC: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyStableThree,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
@ -88,12 +73,7 @@ export const strategyUSDC: IReserveParams = {
};
export const strategyUSDT: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyStableThree,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
@ -105,12 +85,7 @@ export const strategyUSDT: IReserveParams = {
};
export const strategyAAVE: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: '0',
variableRateSlope2: '0',
stableRateSlope1: '0',
stableRateSlope2: '0',
strategy: rateStrategyAAVE,
baseLTVAsCollateral: '5000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
@ -122,12 +97,7 @@ export const strategyAAVE: IReserveParams = {
};
export const strategyBAT: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileOne,
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
@ -139,12 +109,7 @@ export const strategyBAT: IReserveParams = {
};
export const strategyENJ: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileOne,
baseLTVAsCollateral: '5500',
liquidationThreshold: '6000',
liquidationBonus: '11000',
@ -156,12 +121,7 @@ export const strategyENJ: IReserveParams = {
};
export const strategyWETH: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyWETH,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8250',
liquidationBonus: '10500',
@ -173,12 +133,7 @@ export const strategyWETH: IReserveParams = {
};
export const strategyKNC: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileTwo,
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
@ -190,12 +145,7 @@ export const strategyKNC: IReserveParams = {
};
export const strategyLINK: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileOne,
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
@ -207,12 +157,7 @@ export const strategyLINK: IReserveParams = {
};
export const strategyMANA: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileOne,
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
@ -224,12 +169,7 @@ export const strategyMANA: IReserveParams = {
};
export const strategyMKR: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileOne,
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
@ -241,12 +181,7 @@ export const strategyMKR: IReserveParams = {
};
export const strategyREN: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileOne,
baseLTVAsCollateral: '5500',
liquidationThreshold: '6000',
liquidationBonus: '11000',
@ -258,12 +193,7 @@ export const strategyREN: IReserveParams = {
};
export const strategySNX: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.12).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
strategy: rateStrategyVolatileThree,
baseLTVAsCollateral: '1500',
liquidationThreshold: '4000',
liquidationBonus: '11000',
@ -274,13 +204,9 @@ export const strategySNX: IReserveParams = {
reserveFactor: '3500'
};
// Invalid borrow rates in params currently, replaced with snx params
export const strategyUNI: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: '0',
variableRateSlope2: '0',
stableRateSlope1: '0',
stableRateSlope2: '0',
strategy: rateStrategyVolatileThree,
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
@ -292,12 +218,7 @@ export const strategyUNI: IReserveParams = {
};
export const strategyWBTC: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileTwo,
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
@ -309,12 +230,7 @@ export const strategyWBTC: IReserveParams = {
};
export const strategyYFI: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileOne,
baseLTVAsCollateral: '4000',
liquidationThreshold: '5500',
liquidationBonus: '11500',
@ -326,12 +242,7 @@ export const strategyYFI: IReserveParams = {
};
export const strategyZRX: IReserveParams = {
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
strategy: rateStrategyVolatileOne,
baseLTVAsCollateral: '6000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
@ -340,4 +251,16 @@ export const strategyZRX: IReserveParams = {
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyXSUSHI: IReserveParams = {
strategy: rateStrategyVolatileFour,
baseLTVAsCollateral: '2500',
liquidationThreshold: '4500',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '3500',
};

338
markets/amm/commons.ts Normal file
View File

@ -0,0 +1,338 @@
import BigNumber from 'bignumber.js';
import {
oneEther,
oneRay,
RAY,
ZERO_ADDRESS,
MOCK_CHAINLINK_AGGREGATORS_PRICES,
} from '../../helpers/constants';
import { ICommonConfiguration, eEthereumNetwork } from '../../helpers/types';
// ----------------
// PROTOCOL GLOBAL PARAMS
// ----------------
export const CommonsConfig: ICommonConfiguration = {
MarketId: 'Commons',
ATokenNamePrefix: 'Aave AMM Market',
StableDebtTokenNamePrefix: 'Aave AMM Market stable debt',
VariableDebtTokenNamePrefix: 'Aave AMM Market variable debt',
SymbolPrefix: 'Amm',
ProviderId: 0, // Overriden in index.ts
ProtocolGlobalParams: {
TokenDistributorPercentageBase: '10000',
MockUsdPriceInWei: '5848466240000000',
UsdAddress: '0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96',
NilAddress: '0x0000000000000000000000000000000000000000',
OneAddress: '0x0000000000000000000000000000000000000001',
AaveReferral: '0',
},
// ----------------
// COMMON PROTOCOL PARAMS ACROSS POOLS AND NETWORKS
// ----------------
Mocks: {
AllAssetsInitialPrices: {
...MOCK_CHAINLINK_AGGREGATORS_PRICES,
},
},
// TODO: reorg alphabetically, checking the reason of tests failing
LendingRateOracleRatesCommon: {
WETH: {
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
},
DAI: {
borrowRate: oneRay.multipliedBy(0.039).toFixed(),
},
USDC: {
borrowRate: oneRay.multipliedBy(0.039).toFixed(),
},
USDT: {
borrowRate: oneRay.multipliedBy(0.035).toFixed(),
},
WBTC: {
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
},
UniDAIWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniWBTCWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniAAVEWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniBATWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniDAIUSDC: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniCRVWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniLINKWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniMKRWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniRENWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniSNXWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniUNIWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniUSDCWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniWBTCUSDC: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
UniYFIWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
BptWBTCWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
BptBALWETH: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(),
},
},
// ----------------
// COMMON PROTOCOL ADDRESSES ACROSS POOLS
// ----------------
// If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex
PoolAdmin: {
[eEthereumNetwork.coverage]: undefined,
[eEthereumNetwork.buidlerevm]: undefined,
[eEthereumNetwork.coverage]: undefined,
[eEthereumNetwork.hardhat]: undefined,
[eEthereumNetwork.kovan]: undefined,
[eEthereumNetwork.ropsten]: undefined,
[eEthereumNetwork.main]: undefined,
[eEthereumNetwork.tenderlyMain]: undefined,
},
PoolAdminIndex: 0,
EmergencyAdmin: {
[eEthereumNetwork.hardhat]: undefined,
[eEthereumNetwork.coverage]: undefined,
[eEthereumNetwork.buidlerevm]: undefined,
[eEthereumNetwork.kovan]: undefined,
[eEthereumNetwork.ropsten]: undefined,
[eEthereumNetwork.main]: undefined,
[eEthereumNetwork.tenderlyMain]: undefined,
},
EmergencyAdminIndex: 1,
ProviderRegistry: {
[eEthereumNetwork.kovan]: '0x1E40B561EC587036f9789aF83236f057D1ed2A90',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413',
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413',
},
ProviderRegistryOwner: {
// DEPLOYED WITH CORRECT ADDRESS
[eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f',
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f',
},
LendingRateOracle: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '', // Updated to match Kovan deployment
[eEthereumNetwork.kovan]: '0xd00Bd28FAdDa9d5658D1D4e0c151973146C7A533', //'0xE48F95873855bfd97BF89572DDf5cBC44D9c545b'
[eEthereumNetwork.ropsten]: '0x05dcca805a6562c1bdd0423768754acb6993241b',
[eEthereumNetwork.main]: '', //'0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D', // Need to re-deploy because of onlyOwner
[eEthereumNetwork.tenderlyMain]: '0x8A32f49FFbA88aba6EFF96F45D8BD1D4b3f35c7D',
},
LendingPoolCollateralManager: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0x9269b6453d0d75370c4c85e5a42977a53efdb72a',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C',
[eEthereumNetwork.tenderlyMain]: '0xbd4765210d4167CE2A5b87280D9E8Ee316D5EC7C',
},
LendingPoolConfigurator: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0x36eB31800aa67a9c50df1d56EE01981A6E14Cce5',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '',
[eEthereumNetwork.tenderlyMain]: '',
},
LendingPool: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0x78142De7a1930412E9e50dEB3b80dB284c2dFa3A',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '',
[eEthereumNetwork.tenderlyMain]: '',
},
WethGateway: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0x1c4A1cC35A477aa1cF35DF671d93ACc04d8131E0',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '',
[eEthereumNetwork.tenderlyMain]: '',
},
TokenDistributor: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.kovan]: '0x971efe90088f21dc6a36f610ffed77fc19710708',
[eEthereumNetwork.ropsten]: '0xeba2ea67942b8250d870b12750b594696d02fc9c',
[eEthereumNetwork.main]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae',
[eEthereumNetwork.tenderlyMain]: '0xe3d9988f676457123c5fd01297605efdd0cba1ae',
},
AaveOracle: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0x8fb777d67e9945e2c01936e319057f9d41d559e6', // Need to re-deploy because of onlyOwner
[eEthereumNetwork.ropsten]: ZERO_ADDRESS,
[eEthereumNetwork.main]: '', //'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', // Need to re-deploy because of onlyOwner
[eEthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9',
},
FallbackOracle: {
[eEthereumNetwork.coverage]: '',
[eEthereumNetwork.hardhat]: '',
[eEthereumNetwork.buidlerevm]: '',
[eEthereumNetwork.kovan]: '0x50913E8E1c650E790F8a1E741FF9B1B1bB251dfe',
[eEthereumNetwork.ropsten]: '0xAD1a978cdbb8175b2eaeC47B01404f8AEC5f4F0d',
[eEthereumNetwork.main]: ZERO_ADDRESS,
[eEthereumNetwork.tenderlyMain]: ZERO_ADDRESS,
},
ChainlinkAggregator: {
[eEthereumNetwork.coverage]: {},
[eEthereumNetwork.hardhat]: {},
[eEthereumNetwork.buidlerevm]: {},
[eEthereumNetwork.kovan]: {
USDT: '0x0bF499444525a23E7Bb61997539725cA2e928138',
WBTC: '0xF7904a295A029a3aBDFFB6F12755974a958C7C25',
USDC: '0x64EaC61A2DFda2c3Fa04eED49AA33D021AeC8838',
DAI: '0x22B58f1EbEDfCA50feF632bD73368b2FdA96D541',
UniDAIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F', // Mock oracles
UniWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniAAVEWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniBATWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniDAIUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniCRVWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniLINKWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniMKRWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniRENWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniSNXWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniUNIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniUSDCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniWBTCUSDC: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
UniYFIWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
BptWBTCWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
BptBALWETH: '0x5699302154A020FB1DE2B1d39f4c73785A235d8F',
USD: '0x9326BFA02ADD2366b30bacB125260Af641031331',
},
[eEthereumNetwork.ropsten]: {},
[eEthereumNetwork.main]: {
USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46',
WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8',
USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4',
DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4',
UniDAIWETH: '0x66a6b87a18db78086acda75b7720dc47cdabcc05',
UniWBTCWETH: '0x7004BB6F2013F13C54899309cCa029B49707E547',
UniAAVEWETH: '0xB525547968610395B60085bDc8033FFeaEaa5F64',
UniBATWETH: '0xB394D8a1CE721630Cbea8Ec110DCEf0D283EDE3a',
UniDAIUSDC: '0x3B148Fa5E8297DB64262442052b227328730EA81',
UniCRVWETH: '0x10F7078e2f29802D2AC78045F61A69aE0883535A',
UniLINKWETH: '0x30adCEfA5d483284FD79E1eFd54ED3e0A8eaA632',
UniMKRWETH: '0xEBF4A448ff3D835F8FA883941a3E9D5E74B40B5E',
UniRENWETH: '0xe2f7C06906A9dB063C28EB5c71B6Ab454e5222dD',
UniSNXWETH: '0x29bfee7E90572Abf1088a58a145a10D051b78E46',
UniUNIWETH: '0xC2E93e8121237A885A00627975eB06C7BF9808d6',
UniUSDCWETH: '0x71c4a2173CE3620982DC8A7D870297533360Da4E',
UniWBTCUSDC: '0x11f4ba2227F21Dc2A9F0b0e6Ea740369d580a212',
UniYFIWETH: '0x664223b8Bb0934aE0970e601F452f75AaCe9Aa2A',
BptWBTCWETH: '0x4CA8D8fC2b4fCe8A2dcB71Da884bba042d48E067',
BptBALWETH: '0x2e4e78936b100be6Ef85BCEf7FB25bC770B02B85',
USD: '0x9326BFA02ADD2366b30bacB125260Af641031331',
},
[eEthereumNetwork.tenderlyMain]: {
USDT: '0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46',
WBTC: '0xdeb288F737066589598e9214E782fa5A8eD689e8',
USDC: '0x986b5E1e1755e3C2440e960477f25201B0a8bbD4',
DAI: '0x773616E4d11A78F511299002da57A0a94577F1f4',
UniDAIWETH: '0x66a6b87a18db78086acda75b7720dc47cdabcc05',
UniWBTCWETH: '0x7004BB6F2013F13C54899309cCa029B49707E547',
UniAAVEWETH: '0xB525547968610395B60085bDc8033FFeaEaa5F64',
UniBATWETH: '0xB394D8a1CE721630Cbea8Ec110DCEf0D283EDE3a',
UniDAIUSDC: '0x3B148Fa5E8297DB64262442052b227328730EA81',
UniCRVWETH: '0x10F7078e2f29802D2AC78045F61A69aE0883535A',
UniLINKWETH: '0x30adCEfA5d483284FD79E1eFd54ED3e0A8eaA632',
UniMKRWETH: '0xEBF4A448ff3D835F8FA883941a3E9D5E74B40B5E',
UniRENWETH: '0xe2f7C06906A9dB063C28EB5c71B6Ab454e5222dD',
UniSNXWETH: '0x29bfee7E90572Abf1088a58a145a10D051b78E46',
UniUNIWETH: '0xC2E93e8121237A885A00627975eB06C7BF9808d6',
UniUSDCWETH: '0x71c4a2173CE3620982DC8A7D870297533360Da4E',
UniWBTCUSDC: '0x11f4ba2227F21Dc2A9F0b0e6Ea740369d580a212',
UniYFIWETH: '0x664223b8Bb0934aE0970e601F452f75AaCe9Aa2A',
BptWBTCWETH: '0x4CA8D8fC2b4fCe8A2dcB71Da884bba042d48E067',
BptBALWETH: '0x2e4e78936b100be6Ef85BCEf7FB25bC770B02B85',
USD: '0x9326BFA02ADD2366b30bacB125260Af641031331',
},
},
ReserveAssets: {
[eEthereumNetwork.coverage]: {},
[eEthereumNetwork.hardhat]: {},
[eEthereumNetwork.buidlerevm]: {},
[eEthereumNetwork.main]: {},
[eEthereumNetwork.kovan]: {},
[eEthereumNetwork.ropsten]: {},
[eEthereumNetwork.tenderlyMain]: {},
},
ReservesConfig: {},
ATokenDomainSeparator: {
[eEthereumNetwork.coverage]:
'0x95b73a72c6ecf4ccbbba5178800023260bad8e75cdccdb8e4827a2977a37c820',
[eEthereumNetwork.hardhat]:
'0xbae024d959c6a022dc5ed37294cd39c141034b2ae5f02a955cce75c930a81bf5',
[eEthereumNetwork.buidlerevm]:
'0xbae024d959c6a022dc5ed37294cd39c141034b2ae5f02a955cce75c930a81bf5',
[eEthereumNetwork.kovan]: '',
[eEthereumNetwork.ropsten]: '',
[eEthereumNetwork.main]: '',
[eEthereumNetwork.tenderlyMain]: '',
},
WETH: {
[eEthereumNetwork.coverage]: '', // deployed in local evm
[eEthereumNetwork.hardhat]: '', // deployed in local evm
[eEthereumNetwork.buidlerevm]: '', // deployed in local evm
[eEthereumNetwork.kovan]: '0xd0a1e359811322d97991e03f863a0c30c2cf029c',
[eEthereumNetwork.ropsten]: '0xc778417e063141139fce010982780140aa0cd5ab',
[eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
[eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
},
ReserveFactorTreasuryAddress: {
[eEthereumNetwork.coverage]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.hardhat]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.buidlerevm]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.kovan]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.ropsten]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
[eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c',
},
};

137
markets/amm/index.ts Normal file
View File

@ -0,0 +1,137 @@
import { oneRay, ZERO_ADDRESS } from '../../helpers/constants';
import { IAmmConfiguration, eEthereumNetwork } from '../../helpers/types';
import { CommonsConfig } from './commons';
import {
strategyDAI,
strategyUSDC,
strategyUSDT,
strategyWETH,
strategyWBTC,
strategyWBTCWETH,
strategyDAIWETH,
strategyAAVEWETH,
strategyBATWETH,
strategyDAIUSDC,
strategyCRVWETH,
strategyLINKWETH,
strategyMKRWETH,
strategyRENWETH,
strategySNXWETH,
strategyUNIWETH,
strategyUSDCWETH,
strategyWBTCUSDC,
strategyYFIWETH,
strategyBALWETH,
} from './reservesConfigs';
// ----------------
// POOL--SPECIFIC PARAMS
// ----------------
export const AmmConfig: IAmmConfiguration = {
...CommonsConfig,
MarketId: 'Aave AMM market',
ProviderId: 2,
ReservesConfig: {
WETH: strategyWETH,
DAI: strategyDAI,
USDC: strategyUSDC,
USDT: strategyUSDT,
WBTC: strategyWBTC,
UniDAIWETH: strategyDAIWETH,
UniWBTCWETH: strategyWBTCWETH,
UniAAVEWETH: strategyAAVEWETH,
UniBATWETH: strategyBATWETH,
UniDAIUSDC: strategyDAIUSDC,
UniCRVWETH: strategyCRVWETH,
UniLINKWETH: strategyLINKWETH,
UniMKRWETH: strategyMKRWETH,
UniRENWETH: strategyRENWETH,
UniSNXWETH: strategySNXWETH,
UniUNIWETH: strategyUNIWETH,
UniUSDCWETH: strategyUSDCWETH,
UniWBTCUSDC: strategyWBTCUSDC,
UniYFIWETH: strategyYFIWETH,
BptWBTCWETH: strategyWBTCWETH,
BptBALWETH: strategyBALWETH,
},
ReserveAssets: {
[eEthereumNetwork.buidlerevm]: {},
[eEthereumNetwork.hardhat]: {},
[eEthereumNetwork.coverage]: {},
[eEthereumNetwork.kovan]: {
DAI: '0xFf795577d9AC8bD7D90Ee22b6C1703490b6512FD',
USDC: '0xe22da380ee6B445bb8273C81944ADEB6E8450422',
USDT: '0x13512979ADE267AB5100878E2e0f485B568328a4',
WBTC: '0xD1B98B6607330172f1D991521145A22BCe793277',
WETH: '0xd0a1e359811322d97991e03f863a0c30c2cf029c',
UniDAIWETH: '0x0C652EeEA3d7D35759ba1E16183F1D89C386C9ea',
UniWBTCWETH: '0x796d562B1dF5b9dc85A4612187B6f29Ed213d960',
UniAAVEWETH: '0x657A7B8b46F35C5C6583AEF43824744B236EF826',
UniBATWETH: '0xf8CEBA8b16579956B3aE4B5D09002a30f873F783',
UniDAIUSDC: '0x8e80b7a7531c276dD1dBEC2f1Cc281c11c859e62',
UniCRVWETH: '0x9c31b7538467bF0b01e6d5fA789e66Ce540a521e',
UniLINKWETH: '0x5Acab7f8B79620ec7127A96E5D8837d2124D5D7c',
UniMKRWETH: '0xB0C6EC5d58ddbF4cd1e419A56a19924E9904e4Dd',
UniRENWETH: '0xcF428637A9f8Af21920Bc0A94fd81071bc790105',
UniSNXWETH: '0xc8F2a0d698f675Ece74042e9fB06ea52b9517521',
UniUNIWETH: '0xcC99A5f95a86d30e3DeF113bCf22f00ecF90D050',
UniUSDCWETH: '0x8C00D2428ed1857E61652aca663323A85E6e76a9',
UniWBTCUSDC: '0x3d35B5F289f55A580e6F85eE22E6a8f57053b966',
UniYFIWETH: '0x5af95ddFACC150a1695A3Fc606459fd0dE57b91f',
BptWBTCWETH: '0x110569E3261bC0934dA637b019f6f1b6F50ec574',
BptBALWETH: '0xad01D8e0Fa9EAA8Fe76dA30CFb1BCe12707aE6c5',
},
[eEthereumNetwork.ropsten]: {
},
[eEthereumNetwork.main]: {
DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599',
WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
UniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11',
UniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940',
UniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f',
UniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838',
UniDAIUSDC: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5',
UniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE',
UniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974',
UniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225',
UniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c',
UniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47',
UniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17',
UniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc',
UniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416',
UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28',
BptWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5',
BptBALWETH: '0x59A19D8c652FA0284f44113D0ff9aBa70bd46fB4',
},
[eEthereumNetwork.tenderlyMain]: {
DAI: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
USDC: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
USDT: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
WBTC: '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599',
WETH: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
UniDAIWETH: '0xA478c2975Ab1Ea89e8196811F51A7B7Ade33eB11',
UniWBTCWETH: '0xBb2b8038a1640196FbE3e38816F3e67Cba72D940',
UniAAVEWETH: '0xDFC14d2Af169B0D36C4EFF567Ada9b2E0CAE044f',
UniBATWETH: '0xB6909B960DbbE7392D405429eB2b3649752b4838',
UniDAIUSDC: '0xAE461cA67B15dc8dc81CE7615e0320dA1A9aB8D5',
UniCRVWETH: '0x3dA1313aE46132A397D90d95B1424A9A7e3e0fCE',
UniLINKWETH: '0xa2107FA5B38d9bbd2C461D6EDf11B11A50F6b974',
UniMKRWETH: '0xC2aDdA861F89bBB333c90c492cB837741916A225',
UniRENWETH: '0x8Bd1661Da98EBDd3BD080F0bE4e6d9bE8cE9858c',
UniSNXWETH: '0x43AE24960e5534731Fc831386c07755A2dc33D47',
UniUNIWETH: '0xd3d2E2692501A5c9Ca623199D38826e513033a17',
UniUSDCWETH: '0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc',
UniWBTCUSDC: '0x004375Dff511095CC5A197A54140a24eFEF3A416',
UniYFIWETH: '0x2fDbAdf3C4D5A8666Bc06645B8358ab803996E28',
BptWBTCWETH: '0x1efF8aF5D577060BA4ac8A29A13525bb0Ee2A3D5',
BptBALWETH: '0x59A19D8c652FA0284f44113D0ff9aBa70bd46fB4',
},
},
};
export default AmmConfig;

View File

@ -0,0 +1,36 @@
import BigNumber from 'bignumber.js';
import { oneRay } from '../../helpers/constants';
import { IInterestRateStrategyParams } from '../../helpers/types';
// DAIWETH WBTCWETH AAVEWETH BATWETH DAIUSDC CRVWETH LINKWETH MKRWETH RENWETH SNXWETH UNIWETH USDCWETH WBTCUSDC YFIWETH
export const rateStrategyAmmBase: IInterestRateStrategyParams = {
name: "rateStrategyAmmBase",
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0.03).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.10).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3.00).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}
// WETH WBTC
export const rateStrategyBaseOne: IInterestRateStrategyParams = {
name: "rateStrategyBaseOne",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
}
// DAI USDC USDT
export const rateStrategyStable: IInterestRateStrategyParams = {
name: "rateStrategyStable",
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
}

View File

@ -0,0 +1,247 @@
import { eContractid, IReserveParams} from '../../helpers/types';
import {
rateStrategyAmmBase,
rateStrategyStable,
rateStrategyBaseOne,
} from './rateStrategies';
export const strategyWETH: IReserveParams = {
strategy: rateStrategyBaseOne,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8250',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyWBTC: IReserveParams = {
strategy: rateStrategyBaseOne,
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '8',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyDAI: IReserveParams = {
strategy: rateStrategyStable,
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyUSDC: IReserveParams = {
strategy: rateStrategyStable,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyUSDT: IReserveParams = {
strategy: rateStrategyStable,
baseLTVAsCollateral: '-1',
liquidationThreshold: '8500',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyDAIWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyWBTCWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategyAAVEWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '500'
};
export const strategyBATWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategyDAIUSDC: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyCRVWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '5000',
liquidationThreshold: '6000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategyLINKWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategyMKRWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategyRENWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategySNXWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '4000',
liquidationThreshold: '6000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyUNIWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategyUSDCWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyWBTCUSDC: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategyYFIWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '5000',
liquidationThreshold: '6000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
};
export const strategyBALWETH: IReserveParams = {
strategy: rateStrategyAmmBase,
baseLTVAsCollateral: '6000',
liquidationThreshold: '7000',
liquidationBonus: '11500',
borrowingEnabled: true,
stableBorrowRateEnabled: false,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1500'
}

View File

View File

@ -0,0 +1 @@

View File

View File

0
markets/bsc/commons.ts Normal file
View File

1
markets/bsc/index.ts Normal file
View File

@ -0,0 +1 @@

View File

View File

144
markets/matic/commons.ts Normal file
View File

@ -0,0 +1,144 @@
import BigNumber from 'bignumber.js';
import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants';
import { ICommonConfiguration, ePolygonNetwork } from '../../helpers/types';
// ----------------
// PROTOCOL GLOBAL PARAMS
// ----------------
export const CommonsConfig: ICommonConfiguration = {
MarketId: 'Commons',
ATokenNamePrefix: 'Aave Matic Market',
StableDebtTokenNamePrefix: 'Aave Matic Market stable debt',
VariableDebtTokenNamePrefix: 'Aave Matic Market variable debt',
SymbolPrefix: 'm',
ProviderId: 0, // Overriden in index.ts
ProtocolGlobalParams: {
TokenDistributorPercentageBase: '10000',
MockUsdPriceInWei: '5848466240000000',
UsdAddress: '0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96',
NilAddress: '0x0000000000000000000000000000000000000000',
OneAddress: '0x0000000000000000000000000000000000000001',
AaveReferral: '0',
},
// ----------------
// COMMON PROTOCOL PARAMS ACROSS POOLS AND NETWORKS
// ----------------
Mocks: {
AllAssetsInitialPrices: {
...MOCK_CHAINLINK_AGGREGATORS_PRICES,
},
},
// TODO: reorg alphabetically, checking the reason of tests failing
LendingRateOracleRatesCommon: {
WETH: {
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
},
DAI: {
borrowRate: oneRay.multipliedBy(0.039).toFixed(),
},
USDC: {
borrowRate: oneRay.multipliedBy(0.039).toFixed(),
},
USDT: {
borrowRate: oneRay.multipliedBy(0.035).toFixed(),
},
WBTC: {
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
},
WMATIC: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(), // TEMP
},
},
// ----------------
// COMMON PROTOCOL ADDRESSES ACROSS POOLS
// ----------------
// If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex
PoolAdmin: {
[ePolygonNetwork.mumbai]: undefined,
[ePolygonNetwork.matic]: undefined,
},
PoolAdminIndex: 0,
EmergencyAdmin: {
[ePolygonNetwork.mumbai]: undefined,
[ePolygonNetwork.matic]: undefined,
},
LendingPool: {
[ePolygonNetwork.mumbai]: '',
[ePolygonNetwork.matic]: '0xABdC61Cd16e5111f335f4135B7A0e65Cc7F86327',
},
LendingPoolConfigurator: {
[ePolygonNetwork.mumbai]: '',
[ePolygonNetwork.matic]: '0x17c4A170FFF882862F656597889016D3a6073534',
},
EmergencyAdminIndex: 1,
ProviderRegistry: {
[ePolygonNetwork.mumbai]: '0x569859d41499B4dDC28bfaA43915051FF0A38a6F', // TEMP
[ePolygonNetwork.matic]: '0x28334e4791860a0c1eCF89a62B973ba04a5d643F', // TEMP
},
ProviderRegistryOwner: {
[ePolygonNetwork.mumbai]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP
[ePolygonNetwork.matic]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', // TEMP
},
LendingRateOracle: {
[ePolygonNetwork.mumbai]: '',
[ePolygonNetwork.matic]: '',
},
LendingPoolCollateralManager: {
[ePolygonNetwork.mumbai]: '',
[ePolygonNetwork.matic]: '0x9Af76e0575D139570D3B4c821567Fe935E8c25C5',
},
TokenDistributor: {
[ePolygonNetwork.mumbai]: '',
[ePolygonNetwork.matic]: '',
},
WethGateway: {
[ePolygonNetwork.mumbai]: '',
[ePolygonNetwork.matic]: '0x15A46f5073789b7D16F6F46632aE50Bae838d938',
},
AaveOracle: {
[ePolygonNetwork.mumbai]: '',
[ePolygonNetwork.matic]: '0x1B38fa90596F2C25bCf1B193A6c6a718349AFDfC',
},
FallbackOracle: {
[ePolygonNetwork.mumbai]: ZERO_ADDRESS,
[ePolygonNetwork.matic]: ZERO_ADDRESS,
},
ChainlinkAggregator: {
[ePolygonNetwork.matic]: {
DAI: '0x4746DeC9e833A82EC7C2C1356372CcF2cfcD2F3D',
USDC: '0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7',
USDT: '0x0A6513e40db6EB1b165753AD52E80663aeA50545',
WBTC: '0xc907E116054Ad103354f2D350FD2514433D57F6f',
WETH: '0xF9680D99D6C9589e2a93a78A04A279e509205945',
WMATIC: '0xAB594600376Ec9fD91F8e885dADF0CE036862dE0',
},
[ePolygonNetwork.mumbai]: {
DAI: ZERO_ADDRESS,
USDC: ZERO_ADDRESS,
USDT: ZERO_ADDRESS,
WBTC: ZERO_ADDRESS,
WMATIC: ZERO_ADDRESS,
},
},
ReserveAssets: {
[ePolygonNetwork.matic]: {},
[ePolygonNetwork.mumbai]: {},
},
ReservesConfig: {},
ATokenDomainSeparator: {
[ePolygonNetwork.mumbai]: '',
[ePolygonNetwork.matic]: '',
},
WETH: {
[ePolygonNetwork.mumbai]: '0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889', // WMATIC address (untested)
[ePolygonNetwork.matic]: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', // WMATIC address
},
ReserveFactorTreasuryAddress: {
[ePolygonNetwork.mumbai]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP
[ePolygonNetwork.matic]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP
},
};

50
markets/matic/index.ts Normal file
View File

@ -0,0 +1,50 @@
import { oneRay, ZERO_ADDRESS } from '../../helpers/constants';
import { IMaticConfiguration, ePolygonNetwork } from '../../helpers/types';
import { CommonsConfig } from './commons';
import {
strategyDAI,
strategyUSDC,
strategyUSDT,
strategyWBTC,
strategyWETH,
strategyMATIC,
} from './reservesConfigs';
// ----------------
// POOL--SPECIFIC PARAMS
// ----------------
export const MaticConfig: IMaticConfiguration = {
...CommonsConfig,
MarketId: 'Matic Market',
ProviderId: 3, // Unknown?
ReservesConfig: {
DAI: strategyDAI,
USDC: strategyUSDC,
USDT: strategyUSDT,
WBTC: strategyWBTC,
WETH: strategyWETH,
WMATIC: strategyMATIC,
},
ReserveAssets: {
[ePolygonNetwork.matic]: {
DAI: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063',
USDC: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174',
USDT: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F',
WBTC: '0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6',
WETH: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619',
WMATIC: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270',
},
[ePolygonNetwork.mumbai]: { // Mock tokens with a simple "mint" external function, except wmatic
DAI: '0x13b3fda609C1eeb23b4F4b69257840760dCa6C4a',
USDC: '0x52b63223994433FdE2F1350Ba69Dfd2779f06ABA',
USDT: '0xB3abd1912F586fDFFa13606882c28E27913853d2',
WBTC: '0x393E3512d45a956A628124665672312ea86930Ba',
WETH: '0x53CDb16B8C031B779e996406546614E5F05BC4Bf',
WMATIC: '0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889',
},
},
};
export default MaticConfig;

View File

@ -0,0 +1,91 @@
import BigNumber from 'bignumber.js';
import { oneRay } from '../../helpers/constants';
import { IInterestRateStrategyParams } from '../../helpers/types';
// BUSD SUSD
export const rateStrategyStableOne: IInterestRateStrategyParams = {
name: "rateStrategyStableOne",
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
};
// DAI TUSD
export const rateStrategyStableTwo: IInterestRateStrategyParams = {
name: "rateStrategyStableTwo",
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
}
// USDC USDT
export const rateStrategyStableThree: IInterestRateStrategyParams = {
name: "rateStrategyStableThree",
optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
}
// WETH
export const rateStrategyWETH: IInterestRateStrategyParams = {
name: "rateStrategyWETH",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
}
// AAVE
export const rateStrategyAAVE: IInterestRateStrategyParams = {
name: "rateStrategyAAVE",
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: '0',
variableRateSlope2: '0',
stableRateSlope1: '0',
stableRateSlope2: '0',
}
// BAT ENJ LINK MANA MKR REN YFI ZRX
export const rateStrategyVolatileOne: IInterestRateStrategyParams = {
name: "rateStrategyVolatileOne",
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}
// KNC WBTC
export const rateStrategyVolatileTwo: IInterestRateStrategyParams = {
name: "rateStrategyVolatileTwo",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}
// SNX
export const rateStrategyVolatileThree: IInterestRateStrategyParams = {
name: "rateStrategyVolatileThree",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}

View File

@ -0,0 +1,85 @@
// import BigNumber from 'bignumber.js';
// import { oneRay } from '../../helpers/constants';
import { eContractid, IReserveParams } from '../../helpers/types';
import {
rateStrategyStableOne,
rateStrategyStableTwo,
rateStrategyStableThree,
rateStrategyWETH,
rateStrategyAAVE,
rateStrategyVolatileOne,
rateStrategyVolatileTwo,
rateStrategyVolatileThree,
} from './rateStrategies';
export const strategyDAI: IReserveParams = {
strategy: rateStrategyStableTwo,
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyUSDC: IReserveParams = {
strategy: rateStrategyStableThree,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyUSDT: IReserveParams = {
strategy: rateStrategyStableThree,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyWETH: IReserveParams = {
strategy: rateStrategyWETH,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8250',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyWBTC: IReserveParams = {
strategy: rateStrategyVolatileTwo,
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '8',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategyMATIC: IReserveParams = {
strategy: rateStrategyVolatileOne, //Temp?
baseLTVAsCollateral: '5000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};

0
markets/ovm/commons.ts Normal file
View File

1
markets/ovm/index.ts Normal file
View File

@ -0,0 +1 @@

View File

View File

View File

1
markets/solana/index.ts Normal file
View File

@ -0,0 +1 @@

View File

View File

120
markets/xdai/commons.ts Normal file
View File

@ -0,0 +1,120 @@
import BigNumber from 'bignumber.js';
import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants';
import { ICommonConfiguration, eXDaiNetwork } from '../../helpers/types';
// ----------------
// PROTOCOL GLOBAL PARAMS
// ----------------
export const CommonsConfig: ICommonConfiguration = {
MarketId: 'Commons',
ATokenNamePrefix: 'Aave XDAI Market',
StableDebtTokenNamePrefix: 'Aave XDAI Market stable debt',
VariableDebtTokenNamePrefix: 'Aave XDAI Market variable debt',
SymbolPrefix: 'm',
ProviderId: 0, // Overriden in index.ts
ProtocolGlobalParams: {
TokenDistributorPercentageBase: '10000',
MockUsdPriceInWei: '5848466240000000',
UsdAddress: '0x10F7Fc1F91Ba351f9C629c5947AD69bD03C05b96',
NilAddress: '0x0000000000000000000000000000000000000000',
OneAddress: '0x0000000000000000000000000000000000000001',
AaveReferral: '0',
},
// ----------------
// COMMON PROTOCOL PARAMS ACROSS POOLS AND NETWORKS
// ----------------
Mocks: {
AllAssetsInitialPrices: {
...MOCK_CHAINLINK_AGGREGATORS_PRICES,
},
},
// TODO: reorg alphabetically, checking the reason of tests failing
LendingRateOracleRatesCommon: {
WETH: {
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
},
DAI: {
borrowRate: oneRay.multipliedBy(0.039).toFixed(),
},
USDC: {
borrowRate: oneRay.multipliedBy(0.039).toFixed(),
},
USDT: {
borrowRate: oneRay.multipliedBy(0.035).toFixed(),
},
WBTC: {
borrowRate: oneRay.multipliedBy(0.03).toFixed(),
},
STAKE: {
borrowRate: oneRay.multipliedBy(0.05).toFixed(), // TEMP
},
},
// ----------------
// COMMON PROTOCOL ADDRESSES ACROSS POOLS
// ----------------
// If PoolAdmin/emergencyAdmin is set, will take priority over PoolAdminIndex/emergencyAdminIndex
PoolAdmin: {
[eXDaiNetwork.xdai]: undefined,
},
PoolAdminIndex: 0,
EmergencyAdmin: {
[eXDaiNetwork.xdai]: undefined,
},
EmergencyAdminIndex: 1,
ProviderRegistry: {
[eXDaiNetwork.xdai]: '',
},
ProviderRegistryOwner: {
[eXDaiNetwork.xdai]: '',
},
LendingPoolConfigurator: {
[eXDaiNetwork.xdai]: '0',
},
LendingPool: {
[eXDaiNetwork.xdai]: '0',
},
LendingRateOracle: {
[eXDaiNetwork.xdai]: '',
},
LendingPoolCollateralManager: {
[eXDaiNetwork.xdai]: '',
},
TokenDistributor: {
[eXDaiNetwork.xdai]: '',
},
WethGateway: {
[eXDaiNetwork.xdai]: '',
},
AaveOracle: {
[eXDaiNetwork.xdai]: '',
},
FallbackOracle: {
[eXDaiNetwork.xdai]: ZERO_ADDRESS,
},
ChainlinkAggregator: {
[eXDaiNetwork.xdai]: {
DAI: ZERO_ADDRESS,
USDC: ZERO_ADDRESS,
USDT: ZERO_ADDRESS,
WBTC: ZERO_ADDRESS,
STAKE: ZERO_ADDRESS,
},
},
ReserveAssets: {
[eXDaiNetwork.xdai]: {},
},
ReservesConfig: {},
ATokenDomainSeparator: {
[eXDaiNetwork.xdai]: '',
},
WETH: {
[eXDaiNetwork.xdai]: '', // DAI: xDAI is the base token, DAI is also there, We need WXDAI
},
ReserveFactorTreasuryAddress: {
[eXDaiNetwork.xdai]: '', // TEMP
},
};

42
markets/xdai/index.ts Normal file
View File

@ -0,0 +1,42 @@
import { oneRay, ZERO_ADDRESS } from '../../helpers/constants';
import { IXDAIConfiguration, eXDaiNetwork } from '../../helpers/types';
import { CommonsConfig } from './commons';
import {
strategyDAI,
strategyUSDC,
strategyUSDT,
strategyWBTC,
strategyWETH,
strategySTAKE,
} from './reservesConfigs';
// ----------------
// POOL--SPECIFIC PARAMS
// ----------------
export const XDAIConfig: IXDAIConfiguration = {
...CommonsConfig,
MarketId: 'XDAI Market',
ProviderId: 4, // Unknown?
ReservesConfig: {
DAI: strategyDAI,
USDC: strategyUSDC,
USDT: strategyUSDT,
WBTC: strategyWBTC,
WETH: strategyWETH,
STAKE: strategySTAKE,
},
ReserveAssets: {
[eXDaiNetwork.xdai]: {
DAI: '0x44fA8E6f47987339850636F88629646662444217',
USDC: '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83',
USDT: '0x4ECaBa5870353805a9F068101A40E0f32ed605C6',
WBTC: '0x8e5bBbb09Ed1ebdE8674Cda39A0c169401db4252',
WETH: '0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1',
STAKE: '0xb7D311E2Eb55F2f68a9440da38e7989210b9A05e'
},
},
};
export default XDAIConfig;

View File

@ -0,0 +1,91 @@
import BigNumber from 'bignumber.js';
import { oneRay } from '../../helpers/constants';
import { IInterestRateStrategyParams } from '../../helpers/types';
// BUSD SUSD
export const rateStrategyStableOne: IInterestRateStrategyParams = {
name: "rateStrategyStableOne",
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: '0',
stableRateSlope2: '0',
};
// DAI TUSD
export const rateStrategyStableTwo: IInterestRateStrategyParams = {
name: "rateStrategyStableTwo",
optimalUtilizationRate: new BigNumber(0.8).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.75).multipliedBy(oneRay).toFixed(),
}
// USDC USDT
export const rateStrategyStableThree: IInterestRateStrategyParams = {
name: "rateStrategyStableThree",
optimalUtilizationRate: new BigNumber(0.9).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.04).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.02).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(0.60).multipliedBy(oneRay).toFixed(),
}
// WETH
export const rateStrategyWETH: IInterestRateStrategyParams = {
name: "rateStrategyWETH",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(1).multipliedBy(oneRay).toFixed(),
}
// AAVE
export const rateStrategyAAVE: IInterestRateStrategyParams = {
name: "rateStrategyAAVE",
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: '0',
variableRateSlope1: '0',
variableRateSlope2: '0',
stableRateSlope1: '0',
stableRateSlope2: '0',
}
// BAT ENJ LINK MANA MKR REN YFI ZRX
export const rateStrategyVolatileOne: IInterestRateStrategyParams = {
name: "rateStrategyVolatileOne",
optimalUtilizationRate: new BigNumber(0.45).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.07).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}
// KNC WBTC
export const rateStrategyVolatileTwo: IInterestRateStrategyParams = {
name: "rateStrategyVolatileTwo",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}
// SNX
export const rateStrategyVolatileThree: IInterestRateStrategyParams = {
name: "rateStrategyVolatileThree",
optimalUtilizationRate: new BigNumber(0.65).multipliedBy(oneRay).toFixed(),
baseVariableBorrowRate: new BigNumber(0).multipliedBy(oneRay).toFixed(),
variableRateSlope1: new BigNumber(0.08).multipliedBy(oneRay).toFixed(),
variableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
stableRateSlope1: new BigNumber(0.1).multipliedBy(oneRay).toFixed(),
stableRateSlope2: new BigNumber(3).multipliedBy(oneRay).toFixed(),
}

View File

@ -0,0 +1,85 @@
// import BigNumber from 'bignumber.js';
// import { oneRay } from '../../helpers/constants';
import { eContractid, IReserveParams } from '../../helpers/types';
import {
rateStrategyStableOne,
rateStrategyStableTwo,
rateStrategyStableThree,
rateStrategyWETH,
rateStrategyAAVE,
rateStrategyVolatileOne,
rateStrategyVolatileTwo,
rateStrategyVolatileThree,
} from './rateStrategies';
export const strategyDAI: IReserveParams = {
strategy: rateStrategyStableTwo,
baseLTVAsCollateral: '7500',
liquidationThreshold: '8000',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyUSDC: IReserveParams = {
strategy: rateStrategyStableThree,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyUSDT: IReserveParams = {
strategy: rateStrategyStableThree,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8500',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '6',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyWETH: IReserveParams = {
strategy: rateStrategyWETH,
baseLTVAsCollateral: '8000',
liquidationThreshold: '8250',
liquidationBonus: '10500',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '1000'
};
export const strategyWBTC: IReserveParams = {
strategy: rateStrategyVolatileTwo,
baseLTVAsCollateral: '7000',
liquidationThreshold: '7500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '8',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};
export const strategySTAKE: IReserveParams = {
strategy: rateStrategyVolatileOne, //Temp?
baseLTVAsCollateral: '5000',
liquidationThreshold: '6500',
liquidationBonus: '11000',
borrowingEnabled: true,
stableBorrowRateEnabled: true,
reserveDecimals: '18',
aTokenImpl: eContractid.AToken,
reserveFactor: '2000'
};

View File

1
markets/zksync/index.ts Normal file
View File

@ -0,0 +1 @@

Some files were not shown because too many files have changed in this diff Show More