diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index 7e24fc10..79628d82 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -2,9 +2,9 @@ name: Build on: push: - branches: [master] + branches: [master,protocol-2.5] pull_request: - branches: [master] + branches: [master,protocol-2.5] jobs: build: @@ -30,6 +30,20 @@ jobs: run: npm ci - name: Test run: npm run ci:test + - name: Dev deployment + run: npm run aave:evm:dev:migration + - name: Mainnet deployment at Mainnet fork + run: npm run aave:fork:main + env: + ALCHEMY_KEY: ${{ secrets.ALCHEMY_KEY }} + - name: Amm deployment at Mainnet fork + run: npm run amm:fork:main + env: + ALCHEMY_KEY: ${{ secrets.ALCHEMY_KEY }} + - name: Aave deployment at Kovan fork + run: npm run aave:fork:kovan + env: + ALCHEMY_KEY: ${{ secrets.ALCHEMY_KEY }} # - name: Coverage # run: npm run coverage # - uses: codecov/codecov-action@v1 diff --git a/contracts/deployments/ATokensAndRatesHelper.sol b/contracts/deployments/ATokensAndRatesHelper.sol index 400f7ca6..15a5e81a 100644 --- a/contracts/deployments/ATokensAndRatesHelper.sol +++ b/contracts/deployments/ATokensAndRatesHelper.sol @@ -31,7 +31,10 @@ contract ATokensAndRatesHelper is Ownable { uint256 liquidationThreshold; uint256 liquidationBonus; uint256 reserveFactor; + uint256 borrowCap; + uint256 supplyCap; bool stableBorrowingEnabled; + bool borrowingEnabled; } constructor( @@ -73,10 +76,14 @@ contract ATokensAndRatesHelper is Ownable { inputParams[i].liquidationBonus ); - configurator.enableBorrowingOnReserve( - inputParams[i].asset, - inputParams[i].stableBorrowingEnabled - ); + if (inputParams[i].borrowingEnabled) { + configurator.enableBorrowingOnReserve( + inputParams[i].asset, + inputParams[i].borrowCap, + inputParams[i].stableBorrowingEnabled + ); + } + configurator.setSupplyCap(inputParams[i].asset, inputParams[i].supplyCap); configurator.setReserveFactor(inputParams[i].asset, inputParams[i].reserveFactor); } } diff --git a/contracts/interfaces/ILendingPoolConfigurator.sol b/contracts/interfaces/ILendingPoolConfigurator.sol index 7554f2a8..36d0f206 100644 --- a/contracts/interfaces/ILendingPoolConfigurator.sol +++ b/contracts/interfaces/ILendingPoolConfigurator.sol @@ -120,6 +120,18 @@ interface ILendingPoolConfigurator { **/ event ReserveUnfrozen(address indexed asset); + /** + * @dev Emitted when a reserve is paused + * @param asset The address of the underlying asset of the reserve + **/ + event ReservePaused(address indexed asset); + + /** + * @dev Emitted when a reserve is unpaused + * @param asset The address of the underlying asset of the reserve + **/ + event ReserveUnpaused(address indexed asset); + /** * @dev Emitted when a reserve factor is updated * @param asset The address of the underlying asset of the reserve @@ -127,6 +139,20 @@ interface ILendingPoolConfigurator { **/ event ReserveFactorChanged(address indexed asset, uint256 factor); + /** + * @dev Emitted when the borrow cap of a reserve is updated + * @param asset The address of the underlying asset of the reserve + * @param borrowCap The new borrow cap + **/ + event BorrowCapChanged(address indexed asset, uint256 borrowCap); + + /** + * @dev Emitted when the supply cap of a reserve is updated + * @param asset The address of the underlying asset of the reserve + * @param supplyCap The new supply cap + **/ + event SupplyCapChanged(address indexed asset, uint256 supplyCap); + /** * @dev Emitted when the reserve decimals are updated * @param asset The address of the underlying asset of the reserve @@ -176,4 +202,176 @@ interface ILendingPoolConfigurator { address indexed proxy, address indexed implementation ); + + /** + * @dev Emitted when a new risk admin is registered + * @param admin the newly registered admin + **/ + event RiskAdminRegistered(address indexed admin); + + /** + * @dev Emitted when a risk admin is unregistered + * @param admin the unregistered admin + **/ + event RiskAdminUnregistered(address indexed admin); + + /** + * @dev Initializes reserves in batch + * @param input The array of reserves initialization parameters + **/ + function batchInitReserve(InitReserveInput[] calldata input) external; + + /** + * @dev Updates the aToken implementation for the reserve + * @param input The aToken update paramenters + **/ + function updateAToken(UpdateATokenInput calldata input) external; + + /** + * @dev Updates the stable debt token implementation for the reserve + * @param input The stableDebtToken update parameters + **/ + function updateStableDebtToken(UpdateDebtTokenInput calldata input) external; + + /** + * @dev Updates the variable debt token implementation for the asset + * @param input The variableDebtToken update parameters + **/ + function updateVariableDebtToken(UpdateDebtTokenInput calldata input) external; + + /** + * @dev Enables borrowing on a reserve + * @param asset The address of the underlying asset of the reserve + * @param borrowCap The borrow cap for this specific asset, in absolute units of tokens + * @param stableBorrowRateEnabled True if stable borrow rate needs to be enabled by default on this reserve + **/ + function enableBorrowingOnReserve( + address asset, + uint256 borrowCap, + bool stableBorrowRateEnabled + ) external; + + /** + * @dev Disables borrowing on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + function disableBorrowingOnReserve(address asset) external; + + /** + * @dev Configures the reserve collateralization parameters + * all the values are expressed in percentages with two decimals of precision. A valid value is 10000, which means 100.00% + * @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. The values is always above 100%. A value of 105% + * means the liquidator will receive a 5% bonus + **/ + function configureReserveAsCollateral( + address asset, + uint256 ltv, + uint256 liquidationThreshold, + uint256 liquidationBonus + ) external; + + /** + * @dev Enable stable rate borrowing on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + function enableReserveStableRate(address asset) external; + + /** + * @dev Disable stable rate borrowing on a reserve + * @param asset The address of the underlying asset of the reserve + **/ + function disableReserveStableRate(address asset) external; + + /** + * @dev Activates a reserve + * @param asset The address of the underlying asset of the reserve + **/ + function activateReserve(address asset) external; + + /** + * @dev Deactivates a reserve + * @param asset The address of the underlying asset of the reserve + **/ + function deactivateReserve(address asset) external; + + /** + * @dev Freezes a reserve. A frozen reserve doesn't allow any new deposit, borrow or rate swap + * but allows repayments, liquidations, rate rebalances and withdrawals + * @param asset The address of the underlying asset of the reserve + **/ + function freezeReserve(address asset) external; + + /** + * @dev Unfreezes a reserve + * @param asset The address of the underlying asset of the reserve + **/ + function unfreezeReserve(address asset) external; + + /** + * @dev Pauses a reserve. A paused reserve allow now user moves such as deposit, borrow, repay, swap interestrate, liquidate + * @param asset The address of the underlying asset of the reserve + **/ + function pauseReserve(address asset) external; + + /** + * @dev Unpauses a reserve + * @param asset The address of the underlying asset of the reserve + **/ + function unpauseReserve(address asset) external; + + /** + * @dev Updates the reserve factor of a reserve + * @param asset The address of the underlying asset of the reserve + * @param reserveFactor The new reserve factor of the reserve + **/ + function setReserveFactor(address asset, uint256 reserveFactor) external; + + /** + * @dev Sets the interest rate strategy of a reserve + * @param asset The address of the underlying asset of the reserve + * @param rateStrategyAddress The new address of the interest strategy contract + **/ + function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress) + external; + + /** + * @dev pauses or unpauses all the actions of the protocol, including aToken transfers + * @param val true if protocol needs to be paused, false otherwise + **/ + function setPoolPause(bool val) external; + + /** + * @dev Updates the borrow cap of a reserve + * @param asset The address of the underlying asset of the reserve + * @param borrowCap The new borrow of the reserve + **/ + function setBorrowCap(address asset, uint256 borrowCap) external; + + /** + * @dev Updates the supply cap of a reserve + * @param asset The address of the underlying asset of the reserve + * @param supplyCap The new supply of the reserve + **/ + function setSupplyCap(address asset, uint256 supplyCap) external; + + /** + * @dev Registers a new admin with rights on risk related configurations + * @param admin The address of the admin to register + **/ + function registerRiskAdmin(address admin) external; + + /** + * @dev Unegisters a risk admin + * @param admin The address of the admin to unregister + **/ + function unregisterRiskAdmin(address admin) external; + + /** + * @dev Returns wether an address in a risk admin or not + * @param admin The address of the potential admin + **/ + function isRiskAdmin(address admin) external view returns (bool); } diff --git a/contracts/misc/AaveProtocolDataProvider.sol b/contracts/misc/AaveProtocolDataProvider.sol index 56f7c96e..95deb6ea 100644 --- a/contracts/misc/AaveProtocolDataProvider.sol +++ b/contracts/misc/AaveProtocolDataProvider.sol @@ -64,6 +64,7 @@ contract AaveProtocolDataProvider { return aTokens; } + // not returning borrow and supply caps for compatibility, nor pause flag function getReserveConfigurationData(address asset) external view @@ -80,18 +81,35 @@ contract AaveProtocolDataProvider { bool isFrozen ) { - DataTypes.ReserveConfigurationMap memory configuration = + DataTypes.ReserveConfigurationMap memory configuration = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()).getConfiguration(asset); - (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) = configuration - .getParamsMemory(); + (ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) = + configuration.getParamsMemory(); - (isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) = configuration - .getFlagsMemory(); + (isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled, ) = + configuration.getFlagsMemory(); usageAsCollateralEnabled = liquidationThreshold > 0; } + function getReserveCaps(address asset) + external + view + returns (uint256 borrowCap, uint256 supplyCap) { + + (borrowCap, supplyCap) = ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) + .getConfiguration(asset) + .getCapsMemory(); + } + + function getPaused(address asset) external view returns (bool isPaused) { + (, , , , isPaused) = + ILendingPool(ADDRESSES_PROVIDER.getLendingPool()) + .getConfiguration(asset) + .getFlagsMemory(); + } + function getReserveData(address asset) external view diff --git a/contracts/misc/UiPoolDataProvider.sol b/contracts/misc/UiPoolDataProvider.sol index 63dd7a1c..4e4641c3 100644 --- a/contracts/misc/UiPoolDataProvider.sol +++ b/contracts/misc/UiPoolDataProvider.sol @@ -114,11 +114,16 @@ contract UiPoolDataProvider is IUiPoolDataProvider { reserveData.decimals, reserveData.reserveFactor ) = baseData.configuration.getParamsMemory(); + ( + reserveData.borrowCap, + reserveData.supplyCap + ) = baseData.configuration.getCapsMemory(); ( reserveData.isActive, reserveData.isFrozen, reserveData.borrowingEnabled, - reserveData.stableBorrowRateEnabled + reserveData.stableBorrowRateEnabled, + reserveData.isPaused ) = baseData.configuration.getFlagsMemory(); reserveData.usageAsCollateralEnabled = reserveData.baseLTVasCollateral != 0; ( diff --git a/contracts/misc/WalletBalanceProvider.sol b/contracts/misc/WalletBalanceProvider.sol index 3d4a9288..22a6f55e 100644 --- a/contracts/misc/WalletBalanceProvider.sol +++ b/contracts/misc/WalletBalanceProvider.sol @@ -96,7 +96,7 @@ contract WalletBalanceProvider { DataTypes.ReserveConfigurationMap memory configuration = pool.getConfiguration(reservesWithEth[j]); - (bool isActive, , , ) = configuration.getFlagsMemory(); + (bool isActive, , , , ) = configuration.getFlagsMemory(); if (!isActive) { balances[j] = 0; diff --git a/contracts/misc/interfaces/IUiPoolDataProvider.sol b/contracts/misc/interfaces/IUiPoolDataProvider.sol index 34f06d1c..ac7d344a 100644 --- a/contracts/misc/interfaces/IUiPoolDataProvider.sol +++ b/contracts/misc/interfaces/IUiPoolDataProvider.sol @@ -15,11 +15,14 @@ interface IUiPoolDataProvider { uint256 reserveLiquidationThreshold; uint256 reserveLiquidationBonus; uint256 reserveFactor; + uint256 borrowCap; + uint256 supplyCap; bool usageAsCollateralEnabled; bool borrowingEnabled; bool stableBorrowRateEnabled; bool isActive; bool isFrozen; + bool isPaused; // base data uint128 liquidityIndex; uint128 variableBorrowIndex; diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 35c0ac88..d49c98fb 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -465,7 +465,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage ) external override whenNotPaused { FlashLoanLocalVars memory vars; - ValidationLogic.validateFlashloan(assets, amounts); + ValidationLogic.validateFlashloan(assets, amounts, _reserves); address[] memory aTokenAddresses = new address[](assets.length); uint256[] memory premiums = new uint256[](assets.length); @@ -740,6 +740,8 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage ) external override whenNotPaused { require(msg.sender == _reserves[asset].aTokenAddress, Errors.LP_CALLER_MUST_BE_AN_ATOKEN); + ValidationLogic.validateTransfer(_reserves[asset]); + uint256 reserveId = _reserves[asset].id; if (from != to) { diff --git a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol index 49451d92..c1abf2b0 100644 --- a/contracts/protocol/lendingpool/LendingPoolConfigurator.sol +++ b/contracts/protocol/lendingpool/LendingPoolConfigurator.sol @@ -30,22 +30,41 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur using PercentageMath for uint256; using ReserveConfiguration for DataTypes.ReserveConfigurationMap; - ILendingPoolAddressesProvider internal addressesProvider; - ILendingPool internal pool; + ILendingPoolAddressesProvider internal _addressesProvider; + ILendingPool internal _pool; + + mapping(address => bool) private _riskAdmins; modifier onlyPoolAdmin { - require(addressesProvider.getPoolAdmin() == msg.sender, Errors.CALLER_NOT_POOL_ADMIN); + require(_addressesProvider.getPoolAdmin() == msg.sender, Errors.CALLER_NOT_POOL_ADMIN); _; } modifier onlyEmergencyAdmin { require( - addressesProvider.getEmergencyAdmin() == msg.sender, + _addressesProvider.getEmergencyAdmin() == msg.sender, Errors.LPC_CALLER_NOT_EMERGENCY_ADMIN ); _; } + modifier onlyEmergencyOrPoolAdmin { + require( + _addressesProvider.getEmergencyAdmin() == msg.sender || + _addressesProvider.getPoolAdmin() == msg.sender, + Errors.LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN + ); + _; + } + + modifier onlyRiskOrPoolAdmins { + require( + _riskAdmins[msg.sender] || _addressesProvider.getPoolAdmin() == msg.sender, + Errors.LPC_CALLER_NOT_RISK_OR_POOL_ADMIN + ); + _; + } + uint256 internal constant CONFIGURATOR_REVISION = 0x1; function getRevision() internal pure override returns (uint256) { @@ -53,15 +72,13 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur } function initialize(ILendingPoolAddressesProvider provider) public initializer { - addressesProvider = provider; - pool = ILendingPool(addressesProvider.getLendingPool()); + _addressesProvider = provider; + _pool = ILendingPool(_addressesProvider.getLendingPool()); } - /** - * @dev Initializes reserves in batch - **/ - function batchInitReserve(InitReserveInput[] calldata input) external onlyPoolAdmin { - ILendingPool cachedPool = pool; + /// @inheritdoc ILendingPoolConfigurator + function batchInitReserve(InitReserveInput[] calldata input) external override onlyPoolAdmin { + ILendingPool cachedPool = _pool; for (uint256 i = 0; i < input.length; i++) { _initReserve(cachedPool, input[i]); } @@ -128,6 +145,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur currentConfig.setDecimals(input.underlyingAssetDecimals); currentConfig.setActive(true); + currentConfig.setPaused(false); currentConfig.setFrozen(false); pool.setConfiguration(input.underlyingAsset, currentConfig.data); @@ -141,17 +159,16 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur ); } - /** - * @dev Updates the aToken implementation for the reserve - **/ - function updateAToken(UpdateATokenInput calldata input) external onlyPoolAdmin { - ILendingPool cachedPool = pool; + /// @inheritdoc ILendingPoolConfigurator + function updateAToken(UpdateATokenInput calldata input) external override onlyPoolAdmin { + ILendingPool cachedPool = _pool; DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - bytes memory encodedCall = abi.encodeWithSelector( + bytes memory encodedCall = + abi.encodeWithSelector( IInitializableAToken.initialize.selector, cachedPool, input.treasury, @@ -163,26 +180,25 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur input.params ); - _upgradeTokenImplementation( - reserveData.aTokenAddress, - input.implementation, - encodedCall - ); + _upgradeTokenImplementation(reserveData.aTokenAddress, input.implementation, encodedCall); emit ATokenUpgraded(input.asset, reserveData.aTokenAddress, input.implementation); } - /** - * @dev Updates the stable debt token implementation for the reserve - **/ - function updateStableDebtToken(UpdateDebtTokenInput calldata input) external onlyPoolAdmin { - ILendingPool cachedPool = pool; + /// @inheritdoc ILendingPoolConfigurator + function updateStableDebtToken(UpdateDebtTokenInput calldata input) + external + override + onlyPoolAdmin + { + ILendingPool cachedPool = _pool; DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); - + (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - bytes memory encodedCall = abi.encodeWithSelector( + bytes memory encodedCall = + abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, cachedPool, input.asset, @@ -206,20 +222,20 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur ); } - /** - * @dev Updates the variable debt token implementation for the asset - **/ + /// @inheritdoc ILendingPoolConfigurator function updateVariableDebtToken(UpdateDebtTokenInput calldata input) external + override onlyPoolAdmin { - ILendingPool cachedPool = pool; + ILendingPool cachedPool = _pool; DataTypes.ReserveData memory reserveData = cachedPool.getReserveData(input.asset); (, , , uint256 decimals, ) = cachedPool.getConfiguration(input.asset).getParamsMemory(); - bytes memory encodedCall = abi.encodeWithSelector( + bytes memory encodedCall = + abi.encodeWithSelector( IInitializableDebtToken.initialize.selector, cachedPool, input.asset, @@ -243,54 +259,42 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur ); } - /** - * @dev Enables borrowing on a reserve - * @param asset The address of the underlying asset of the reserve - * @param stableBorrowRateEnabled True if stable borrow rate needs to be enabled by default on this reserve - **/ - function enableBorrowingOnReserve(address asset, bool stableBorrowRateEnabled) - external - onlyPoolAdmin - { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + /// @inheritdoc ILendingPoolConfigurator + function enableBorrowingOnReserve( + address asset, + uint256 borrowCap, + bool stableBorrowRateEnabled + ) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setBorrowingEnabled(true); + currentConfig.setBorrowCap(borrowCap); currentConfig.setStableRateBorrowingEnabled(stableBorrowRateEnabled); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); + emit BorrowCapChanged(asset, borrowCap); emit BorrowingEnabledOnReserve(asset, stableBorrowRateEnabled); } - /** - * @dev Disables borrowing on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - function disableBorrowingOnReserve(address asset) external onlyPoolAdmin { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + /// @inheritdoc ILendingPoolConfigurator + function disableBorrowingOnReserve(address asset) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setBorrowingEnabled(false); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit BorrowingDisabledOnReserve(asset); } - /** - * @dev Configures the reserve collateralization parameters - * all the values are expressed in percentages with two decimals of precision. A valid value is 10000, which means 100.00% - * @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. The values is always above 100%. A value of 105% - * means the liquidator will receive a 5% bonus - **/ + /// @inheritdoc ILendingPoolConfigurator function configureReserveAsCollateral( address asset, uint256 ltv, uint256 liquidationThreshold, uint256 liquidationBonus - ) external onlyPoolAdmin { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + ) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); //validation of the parameters: the LTV can //only be lower or equal than the liquidation threshold @@ -323,132 +327,168 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur currentConfig.setLiquidationThreshold(liquidationThreshold); currentConfig.setLiquidationBonus(liquidationBonus); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit CollateralConfigurationChanged(asset, ltv, liquidationThreshold, liquidationBonus); } - /** - * @dev Enable stable rate borrowing on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - function enableReserveStableRate(address asset) external onlyPoolAdmin { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + /// @inheritdoc ILendingPoolConfigurator + function enableReserveStableRate(address asset) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setStableRateBorrowingEnabled(true); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit StableRateEnabledOnReserve(asset); } - /** - * @dev Disable stable rate borrowing on a reserve - * @param asset The address of the underlying asset of the reserve - **/ - function disableReserveStableRate(address asset) external onlyPoolAdmin { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + /// @inheritdoc ILendingPoolConfigurator + function disableReserveStableRate(address asset) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setStableRateBorrowingEnabled(false); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit StableRateDisabledOnReserve(asset); } - /** - * @dev Activates a reserve - * @param asset The address of the underlying asset of the reserve - **/ - function activateReserve(address asset) external onlyPoolAdmin { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + /// @inheritdoc ILendingPoolConfigurator + function activateReserve(address asset) external override onlyPoolAdmin { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setActive(true); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit ReserveActivated(asset); } - /** - * @dev Deactivates a reserve - * @param asset The address of the underlying asset of the reserve - **/ - function deactivateReserve(address asset) external onlyPoolAdmin { + /// @inheritdoc ILendingPoolConfigurator + function deactivateReserve(address asset) external override onlyPoolAdmin { _checkNoLiquidity(asset); - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setActive(false); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit ReserveDeactivated(asset); } - /** - * @dev Freezes a reserve. A frozen reserve doesn't allow any new deposit, borrow or rate swap - * but allows repayments, liquidations, rate rebalances and withdrawals - * @param asset The address of the underlying asset of the reserve - **/ - function freezeReserve(address asset) external onlyPoolAdmin { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + /// @inheritdoc ILendingPoolConfigurator + function freezeReserve(address asset) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setFrozen(true); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit ReserveFrozen(asset); } - /** - * @dev Unfreezes a reserve - * @param asset The address of the underlying asset of the reserve - **/ - function unfreezeReserve(address asset) external onlyPoolAdmin { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + /// @inheritdoc ILendingPoolConfigurator + function unfreezeReserve(address asset) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setFrozen(false); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit ReserveUnfrozen(asset); } - /** - * @dev Updates the reserve factor of a reserve - * @param asset The address of the underlying asset of the reserve - * @param reserveFactor The new reserve factor of the reserve - **/ - function setReserveFactor(address asset, uint256 reserveFactor) external onlyPoolAdmin { - DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset); + /// @inheritdoc ILendingPoolConfigurator + function pauseReserve(address asset) external override onlyEmergencyOrPoolAdmin { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); + + currentConfig.setPaused(true); + + _pool.setConfiguration(asset, currentConfig.data); + + emit ReservePaused(asset); + } + + /// @inheritdoc ILendingPoolConfigurator + function unpauseReserve(address asset) external override onlyEmergencyOrPoolAdmin { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); + + currentConfig.setPaused(false); + + _pool.setConfiguration(asset, currentConfig.data); + + emit ReserveUnpaused(asset); + } + + /// @inheritdoc ILendingPoolConfigurator + function setReserveFactor(address asset, uint256 reserveFactor) + external + override + onlyRiskOrPoolAdmins + { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); currentConfig.setReserveFactor(reserveFactor); - pool.setConfiguration(asset, currentConfig.data); + _pool.setConfiguration(asset, currentConfig.data); emit ReserveFactorChanged(asset, reserveFactor); } - /** - * @dev Sets the interest rate strategy of a reserve - * @param asset The address of the underlying asset of the reserve - * @param rateStrategyAddress The new address of the interest strategy contract - **/ + ///@inheritdoc ILendingPoolConfigurator + function setBorrowCap(address asset, uint256 borrowCap) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); + + currentConfig.setBorrowCap(borrowCap); + + _pool.setConfiguration(asset, currentConfig.data); + + emit BorrowCapChanged(asset, borrowCap); + } + + ///@inheritdoc ILendingPoolConfigurator + function setSupplyCap(address asset, uint256 supplyCap) external override onlyRiskOrPoolAdmins { + DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset); + + currentConfig.setSupplyCap(supplyCap); + + _pool.setConfiguration(asset, currentConfig.data); + + emit SupplyCapChanged(asset, supplyCap); + } + + ///@inheritdoc ILendingPoolConfigurator function setReserveInterestRateStrategyAddress(address asset, address rateStrategyAddress) external - onlyPoolAdmin + override + onlyRiskOrPoolAdmins { - pool.setReserveInterestRateStrategyAddress(asset, rateStrategyAddress); + _pool.setReserveInterestRateStrategyAddress(asset, rateStrategyAddress); emit ReserveInterestRateStrategyChanged(asset, rateStrategyAddress); } - /** - * @dev pauses or unpauses all the actions of the protocol, including aToken transfers - * @param val true if protocol needs to be paused, false otherwise - **/ - function setPoolPause(bool val) external onlyEmergencyAdmin { - pool.setPause(val); + /// @inheritdoc ILendingPoolConfigurator + function setPoolPause(bool val) external override onlyEmergencyAdmin { + _pool.setPause(val); + } + + /// @inheritdoc ILendingPoolConfigurator + function registerRiskAdmin(address admin) external override onlyPoolAdmin { + _riskAdmins[admin] = true; + emit RiskAdminRegistered(admin); + } + + /// @inheritdoc ILendingPoolConfigurator + function unregisterRiskAdmin(address admin) external override onlyPoolAdmin { + _riskAdmins[admin] = false; + emit RiskAdminUnregistered(admin); + } + + /// @inheritdoc ILendingPoolConfigurator + function isRiskAdmin(address admin) external view override onlyPoolAdmin returns (bool) { + return _riskAdmins[admin]; } function _initTokenWithProxy(address implementation, bytes memory initParams) @@ -475,7 +515,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur } function _checkNoLiquidity(address asset) internal view { - DataTypes.ReserveData memory reserveData = pool.getReserveData(asset); + DataTypes.ReserveData memory reserveData = _pool.getReserveData(asset); uint256 availableLiquidity = IERC20Detailed(asset).balanceOf(reserveData.aTokenAddress); diff --git a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol index 5649a580..91d8bc50 100644 --- a/contracts/protocol/libraries/configuration/ReserveConfiguration.sol +++ b/contracts/protocol/libraries/configuration/ReserveConfiguration.sol @@ -18,7 +18,10 @@ library ReserveConfiguration { uint256 constant FROZEN_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFF; // prettier-ignore uint256 constant BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFFFFFFFF; // prettier-ignore uint256 constant STABLE_BORROWING_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFFFFF; // prettier-ignore + uint256 constant PAUSED_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFF; // prettier-ignore uint256 constant RESERVE_FACTOR_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000FFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant BORROW_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFF; // prettier-ignore + uint256 constant SUPPLY_CAP_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFF000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFF; // prettier-ignore /// @dev For the LTV, the start bit is 0 (up to 15), hence no bitshifting is needed uint256 constant LIQUIDATION_THRESHOLD_START_BIT_POSITION = 16; @@ -28,13 +31,19 @@ library ReserveConfiguration { uint256 constant IS_FROZEN_START_BIT_POSITION = 57; uint256 constant BORROWING_ENABLED_START_BIT_POSITION = 58; uint256 constant STABLE_BORROWING_ENABLED_START_BIT_POSITION = 59; + uint256 constant IS_PAUSED_START_BIT_POSITION = 60; + // bits 61 62 63 unused yet uint256 constant RESERVE_FACTOR_START_BIT_POSITION = 64; + uint256 constant BORROW_CAP_START_BIT_POSITION = 80; + uint256 constant SUPPLY_CAP_START_BIT_POSITION = 116; uint256 constant MAX_VALID_LTV = 65535; uint256 constant MAX_VALID_LIQUIDATION_THRESHOLD = 65535; uint256 constant MAX_VALID_LIQUIDATION_BONUS = 65535; uint256 constant MAX_VALID_DECIMALS = 255; uint256 constant MAX_VALID_RESERVE_FACTOR = 65535; + uint256 constant MAX_VALID_BORROW_CAP = 68719476735; + uint256 constant MAX_VALID_SUPPLY_CAP = 68719476735; /** * @dev Sets the Loan to Value of the reserve @@ -181,6 +190,26 @@ library ReserveConfiguration { return (self.data & ~FROZEN_MASK) != 0; } + /** + * @dev Sets the paused state of the reserve + * @param self The reserve configuration + * @param paused The paused state + **/ + function setPaused(DataTypes.ReserveConfigurationMap memory self, bool paused) internal pure { + self.data = + (self.data & PAUSED_MASK) | + (uint256(paused ? 1 : 0) << IS_PAUSED_START_BIT_POSITION); + } + + /** + * @dev Gets the paused state of the reserve + * @param self The reserve configuration + * @return The paused state + **/ + function getPaused(DataTypes.ReserveConfigurationMap storage self) internal view returns (bool) { + return (self.data & ~PAUSED_MASK) != 0; + } + /** * @dev Enables or disables borrowing on the reserve * @param self The reserve configuration @@ -264,6 +293,60 @@ library ReserveConfiguration { return (self.data & ~RESERVE_FACTOR_MASK) >> RESERVE_FACTOR_START_BIT_POSITION; } + /** + * @dev Sets the borrow cap of the reserve + * @param self The reserve configuration + * @param borrowCap The borrow cap + **/ + function setBorrowCap(DataTypes.ReserveConfigurationMap memory self, uint256 borrowCap) + internal + pure + { + require(borrowCap <= MAX_VALID_BORROW_CAP, Errors.RC_INVALID_BORROW_CAP); + + self.data = (self.data & BORROW_CAP_MASK) | (borrowCap << BORROW_CAP_START_BIT_POSITION); + } + + /** + * @dev Gets the borrow cap of the reserve + * @param self The reserve configuration + * @return The borrow cap + **/ + function getBorrowCap(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns (uint256) + { + return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION; + } + + /** + * @dev Sets the supply cap of the reserve + * @param self The reserve configuration + * @param supplyCap The supply cap + **/ + function setSupplyCap(DataTypes.ReserveConfigurationMap memory self, uint256 supplyCap) + internal + pure + { + require(supplyCap <= MAX_VALID_SUPPLY_CAP, Errors.RC_INVALID_SUPPLY_CAP); + + self.data = (self.data & SUPPLY_CAP_MASK) | (supplyCap << SUPPLY_CAP_START_BIT_POSITION); + } + + /** + * @dev Gets the supply cap of the reserve + * @param self The reserve configuration + * @return The supply cap + **/ + function getSupplyCap(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns (uint256) + { + return (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION; + } + /** * @dev Gets the configuration flags of the reserve * @param self The reserve configuration @@ -276,6 +359,7 @@ library ReserveConfiguration { bool, bool, bool, + bool, bool ) { @@ -285,14 +369,15 @@ library ReserveConfiguration { (dataLocal & ~ACTIVE_MASK) != 0, (dataLocal & ~FROZEN_MASK) != 0, (dataLocal & ~BORROWING_MASK) != 0, - (dataLocal & ~STABLE_BORROWING_MASK) != 0 + (dataLocal & ~STABLE_BORROWING_MASK) != 0, + (dataLocal & ~PAUSED_MASK) != 0 ); } /** - * @dev Gets the configuration paramters of the reserve + * @dev Gets the configuration paramters of the reserve from storage * @param self The reserve configuration - * @return The state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals + * @return The state params representing ltv, liquidation threshold, liquidation bonus, reserve decimals, reserve factor **/ function getParams(DataTypes.ReserveConfigurationMap storage self) internal @@ -316,10 +401,28 @@ library ReserveConfiguration { ); } + /** + * @dev Gets the caps paramters of the reserve from storage + * @param self The reserve configuration + * @return The state params representing borrow cap and supply cap. + **/ + function getCaps(DataTypes.ReserveConfigurationMap storage self) + internal + view + returns (uint256, uint256) + { + uint256 dataLocal = self.data; + + return ( + (dataLocal & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, + (dataLocal & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION + ); + } + /** * @dev Gets the configuration paramters of the reserve from a memory object * @param self The reserve configuration - * @return The state params representing ltv, liquidation threshold, liquidation bonus, the reserve decimals + * @return The state params representing ltv, liquidation threshold, liquidation bonus, reserve decimals, reserve factor **/ function getParamsMemory(DataTypes.ReserveConfigurationMap memory self) internal @@ -341,6 +444,22 @@ library ReserveConfiguration { ); } + /** + * @dev Gets the caps paramters of the reserve from a memory object + * @param self The reserve configuration + * @return The state params borrow cap and supply cap + **/ + function getCapsMemory(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns (uint256, uint256) + { + return ( + (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION, + (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION + ); + } + /** * @dev Gets the configuration flags of the reserve from a memory object * @param self The reserve configuration @@ -353,6 +472,7 @@ library ReserveConfiguration { bool, bool, bool, + bool, bool ) { @@ -360,7 +480,34 @@ library ReserveConfiguration { (self.data & ~ACTIVE_MASK) != 0, (self.data & ~FROZEN_MASK) != 0, (self.data & ~BORROWING_MASK) != 0, - (self.data & ~STABLE_BORROWING_MASK) != 0 + (self.data & ~STABLE_BORROWING_MASK) != 0, + (self.data & ~PAUSED_MASK) != 0 ); } + + /** + * @dev Gets the supply cap of the reserve from a memory objet + * @param self The reserve configuration + * @return The supply cap + **/ + function getSupplyCapMemory(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns (uint256) + { + return (self.data & ~SUPPLY_CAP_MASK) >> SUPPLY_CAP_START_BIT_POSITION; + } + + /** + * @dev Gets the borrow cap of the reserve from a memory object + * @param self The reserve configuration + * @return The borrow cap + **/ + function getBorrowCapMemory(DataTypes.ReserveConfigurationMap memory self) + internal + pure + returns (uint256) + { + return (self.data & ~BORROW_CAP_MASK) >> BORROW_CAP_START_BIT_POSITION; + } } diff --git a/contracts/protocol/libraries/helpers/Errors.sol b/contracts/protocol/libraries/helpers/Errors.sol index 9729379d..8a2e7653 100644 --- a/contracts/protocol/libraries/helpers/Errors.sol +++ b/contracts/protocol/libraries/helpers/Errors.sol @@ -102,6 +102,13 @@ library Errors { string public constant LP_NOT_CONTRACT = '78'; string public constant SDT_STABLE_DEBT_OVERFLOW = '79'; string public constant SDT_BURN_EXCEEDS_BALANCE = '80'; + string public constant VL_BORROW_CAP_EXCEEDED = '81'; + string public constant RC_INVALID_BORROW_CAP = '82'; + string public constant VL_SUPPLY_CAP_EXCEEDED = '83'; + string public constant RC_INVALID_SUPPLY_CAP = '84'; + string public constant LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN = '85'; + string public constant VL_RESERVE_PAUSED = '86'; + string public constant LPC_CALLER_NOT_RISK_OR_POOL_ADMIN = '87'; enum CollateralManagerErrors { NO_ERROR, @@ -113,6 +120,7 @@ library Errors { NO_ACTIVE_RESERVE, HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD, INVALID_EQUAL_ASSETS_TO_SWAP, - FROZEN_RESERVE + FROZEN_RESERVE, + PAUSED_RESERVE } } diff --git a/contracts/protocol/libraries/logic/ValidationLogic.sol b/contracts/protocol/libraries/logic/ValidationLogic.sol index 32f2de4d..40ef23be 100644 --- a/contracts/protocol/libraries/logic/ValidationLogic.sol +++ b/contracts/protocol/libraries/logic/ValidationLogic.sol @@ -14,6 +14,8 @@ import {UserConfiguration} from '../configuration/UserConfiguration.sol'; import {Errors} from '../helpers/Errors.sol'; import {Helpers} from '../helpers/Helpers.sol'; import {IReserveInterestRateStrategy} from '../../../interfaces/IReserveInterestRateStrategy.sol'; +import {IVariableDebtToken} from '../../../interfaces/IVariableDebtToken.sol'; +import {IStableDebtToken} from '../../../interfaces/IStableDebtToken.sol'; import {DataTypes} from '../types/DataTypes.sol'; /** @@ -39,14 +41,23 @@ library ValidationLogic { * @param amount The amount to be deposited */ function validateDeposit(DataTypes.ReserveData storage reserve, uint256 amount) internal view { - (bool isActive, bool isFrozen, , ) = reserve.configuration.getFlags(); + DataTypes.ReserveConfigurationMap memory reserveConfiguration = reserve.configuration; + (bool isActive, bool isFrozen, , , bool isPaused) = reserveConfiguration.getFlagsMemory(); + (, , , uint256 reserveDecimals, ) = reserveConfiguration.getParamsMemory(); + uint256 supplyCap = reserveConfiguration.getSupplyCapMemory(); require(amount != 0, Errors.VL_INVALID_AMOUNT); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); + require(!isPaused, Errors.VL_RESERVE_PAUSED); require(!isFrozen, Errors.VL_RESERVE_FROZEN); + require( + supplyCap == 0 || + IERC20(reserve.aTokenAddress).totalSupply().add(amount).div(10**reserveDecimals) < + supplyCap, + Errors.VL_SUPPLY_CAP_EXCEEDED + ); } - /** * @dev Validates a withdraw action * @param reserve The reserve object @@ -57,12 +68,13 @@ library ValidationLogic { DataTypes.ReserveData storage reserve, uint256 amount, uint256 userBalance - ) internal view { + ) external view { require(amount != 0, Errors.VL_INVALID_AMOUNT); require(amount <= userBalance, Errors.VL_NOT_ENOUGH_AVAILABLE_USER_BALANCE); - (bool isActive, , , ) = reserve.configuration.getFlags(); + (bool isActive, , , , bool isPaused) = reserve.configuration.getFlags(); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); + require(!isPaused, Errors.VL_RESERVE_PAUSED); } struct ValidateBorrowLocalVars { @@ -73,8 +85,13 @@ library ValidationLogic { uint256 userBorrowBalanceETH; uint256 availableLiquidity; uint256 healthFactor; + uint256 totalSupplyStableDebt; + uint256 totalSupplyVariableDebt; + uint256 reserveDecimals; + uint256 borrowCap; bool isActive; bool isFrozen; + bool isPaused; bool borrowingEnabled; bool stableRateBorrowingEnabled; } @@ -107,14 +124,22 @@ library ValidationLogic { mapping(uint256 => address) storage reserves, uint256 reservesCount, address oracle - ) internal view { + ) external view { ValidateBorrowLocalVars memory vars; - (vars.isActive, vars.isFrozen, vars.borrowingEnabled, vars.stableRateBorrowingEnabled) = reserve - .configuration - .getFlags(); + DataTypes.ReserveConfigurationMap memory reserveConfiguration = reserve.configuration; + (, , , vars.reserveDecimals, ) = reserveConfiguration.getParamsMemory(); + + ( + vars.isActive, + vars.isFrozen, + vars.borrowingEnabled, + vars.stableRateBorrowingEnabled, + vars.isPaused + ) = reserveConfiguration.getFlagsMemory(); require(vars.isActive, Errors.VL_NO_ACTIVE_RESERVE); + require(!vars.isPaused, Errors.VL_RESERVE_PAUSED); require(!vars.isFrozen, Errors.VL_RESERVE_FROZEN); require(amount != 0, Errors.VL_INVALID_AMOUNT); @@ -127,6 +152,19 @@ library ValidationLogic { Errors.VL_INVALID_INTEREST_RATE_MODE_SELECTED ); + vars.totalSupplyStableDebt = IERC20(reserve.stableDebtTokenAddress).totalSupply(); + vars.borrowCap = reserveConfiguration.getBorrowCapMemory(); + vars.totalSupplyVariableDebt = IERC20(reserve.variableDebtTokenAddress).totalSupply(); + + require( + vars.borrowCap == 0 || + vars.totalSupplyStableDebt.add(vars.totalSupplyVariableDebt).add(amount).div( + 10**vars.reserveDecimals + ) < + vars.borrowCap, + Errors.VL_BORROW_CAP_EXCEEDED + ); + ( vars.userCollateralBalanceETH, vars.userBorrowBalanceETH, @@ -204,10 +242,10 @@ library ValidationLogic { address onBehalfOf, uint256 stableDebt, uint256 variableDebt - ) internal view { - bool isActive = reserve.configuration.getActive(); - + ) external view { + (bool isActive, , , , bool isPaused) = reserve.configuration.getFlags(); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); + require(!isPaused, Errors.VL_RESERVE_PAUSED); require(amountSent > 0, Errors.VL_INVALID_AMOUNT); @@ -240,9 +278,11 @@ library ValidationLogic { uint256 variableDebt, DataTypes.InterestRateMode currentRateMode ) external view { - (bool isActive, bool isFrozen, , bool stableRateEnabled) = reserve.configuration.getFlags(); + (bool isActive, bool isFrozen, , bool stableRateEnabled, bool isPaused) = + reserve.configuration.getFlags(); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); + require(!isPaused, Errors.VL_RESERVE_PAUSED); require(!isFrozen, Errors.VL_RESERVE_FROZEN); if (currentRateMode == DataTypes.InterestRateMode.STABLE) { @@ -284,9 +324,10 @@ library ValidationLogic { IERC20 variableDebtToken, address aTokenAddress ) external view { - (bool isActive, , , ) = reserve.configuration.getFlags(); + (bool isActive, , , , bool isPaused) = reserve.configuration.getFlags(); require(isActive, Errors.VL_NO_ACTIVE_RESERVE); + require(!isPaused, Errors.VL_RESERVE_PAUSED); //if the usage ratio is below 95%, no rebalances are needed uint256 totalDebt = @@ -313,10 +354,11 @@ library ValidationLogic { * @dev Validates the action of setting an asset as collateral * @param reserve The state of the reserve that the user is enabling or disabling as collateral */ - function validateSetUseReserveAsCollateral( - DataTypes.ReserveData storage reserve - ) external view { + function validateSetUseReserveAsCollateral(DataTypes.ReserveData storage reserve) external view { uint256 underlyingBalance = IERC20(reserve.aTokenAddress).balanceOf(msg.sender); + bool isPaused = reserve.configuration.getPaused(); + + require(!isPaused, Errors.VL_RESERVE_PAUSED); require(underlyingBalance > 0, Errors.VL_UNDERLYING_BALANCE_NOT_GREATER_THAN_0); } @@ -326,7 +368,14 @@ library ValidationLogic { * @param assets The assets being flashborrowed * @param amounts The amounts for each asset being borrowed **/ - function validateFlashloan(address[] memory assets, uint256[] memory amounts) internal pure { + function validateFlashloan( + address[] memory assets, + uint256[] memory amounts, + mapping(address => DataTypes.ReserveData) storage reservesData + ) external view { + for (uint256 i = 0; i < assets.length; i++) { + require(!reservesData[assets[i]].configuration.getPaused(), Errors.VL_RESERVE_PAUSED); + } require(assets.length == amounts.length, Errors.VL_INCONSISTENT_FLASHLOAN_PARAMS); } @@ -355,6 +404,9 @@ library ValidationLogic { Errors.VL_NO_ACTIVE_RESERVE ); } + if (collateralReserve.configuration.getPaused() || principalReserve.configuration.getPaused()) { + return (uint256(Errors.CollateralManagerErrors.PAUSED_RESERVE), Errors.VL_RESERVE_PAUSED); + } if (userHealthFactor >= GenericLogic.HEALTH_FACTOR_LIQUIDATION_THRESHOLD) { return ( @@ -417,4 +469,12 @@ library ValidationLogic { Errors.VL_HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD ); } + + /** + * @dev Validates a transfer action + * @param reserve The reserve object + */ + function validateTransfer(DataTypes.ReserveData storage reserve) internal view { + require(!reserve.configuration.getPaused(), Errors.VL_RESERVE_PAUSED); + } } diff --git a/contracts/protocol/libraries/types/DataTypes.sol b/contracts/protocol/libraries/types/DataTypes.sol index ffec1d20..5daa68b1 100644 --- a/contracts/protocol/libraries/types/DataTypes.sol +++ b/contracts/protocol/libraries/types/DataTypes.sol @@ -38,8 +38,11 @@ library DataTypes { //bit 57: reserve is frozen //bit 58: borrowing is enabled //bit 59: stable rate borrowing enabled - //bit 60-63: reserved + //bit 60: asset is paused + //bit 61-63: reserved //bit 64-79: reserve factor + //bit 80-115 borrow cap, borrowCap == 0 => disabled + //bit 116-152 supply cap, supplyCap == 0 => disabled uint256 data; } diff --git a/docker-compose.yml b/docker-compose.yml index 7c94bcb3..d81dc720 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,3 +21,5 @@ services: ALCHEMY_KEY: ${ALCHEMY_KEY} TENDERLY_FORK_ID: ${TENDERLY_FORK_ID} TENDERLY_HEAD_ID: ${TENDERLY_HEAD_ID} + DEFENDER_API_KEY: ${DEFENDER_API_KEY} + DEFENDER_SECRET_KEY: ${DEFENDER_SECRET_KEY} diff --git a/hardhat.config.ts b/hardhat.config.ts index 3eaba7c0..10b4402b 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -5,7 +5,12 @@ import { HardhatUserConfig } from 'hardhat/types'; import { accounts } from './test-wallets.js'; 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'; +import { + NETWORKS_RPC_URL, + NETWORKS_DEFAULT_GAS, + BLOCK_TO_FORK, + buildForkConfig, +} from './helper-hardhat-config'; require('dotenv').config(); @@ -16,6 +21,7 @@ import 'hardhat-gas-reporter'; import 'hardhat-typechain'; import '@tenderly/hardhat-tenderly'; import 'solidity-coverage'; +import { fork } from 'child_process'; const SKIP_LOAD = process.env.SKIP_LOAD === 'true'; const DEFAULT_BLOCK_GAS_LIMIT = 12450000; @@ -24,7 +30,6 @@ const HARDFORK = 'istanbul'; const ETHERSCAN_KEY = process.env.ETHERSCAN_KEY || ''; const MNEMONIC_PATH = "m/44'/60'/0'/0"; const MNEMONIC = process.env.MNEMONIC || ''; -const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; // Prevent to load scripts before compilation and typechain if (!SKIP_LOAD) { @@ -57,12 +62,7 @@ const getCommonNetworkConfig = (networkName: eNetwork, networkId: number) => ({ }, }); -const mainnetFork = MAINNET_FORK - ? { - blockNumber: 12012081, - url: NETWORKS_RPC_URL['main'], - } - : undefined; +let forkMode; const buidlerConfig: HardhatUserConfig = { solidity: { @@ -111,7 +111,7 @@ const buidlerConfig: HardhatUserConfig = { privateKey: secretKey, balance, })), - forking: mainnetFork, + forking: buildForkConfig(), }, buidlerevm_docker: { hardfork: 'berlin', diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 552a2e52..3df38000 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -1,4 +1,5 @@ // @ts-ignore +import { HardhatNetworkForkingUserConfig, HardhatUserConfig } from 'hardhat/types'; import { eEthereumNetwork, ePolygonNetwork, @@ -11,9 +12,26 @@ 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 FORK = process.env.FORK || ''; +const FORK_BLOCK_NUMBER = process.env.FORK_BLOCK_NUMBER + ? parseInt(process.env.FORK_BLOCK_NUMBER) + : 0; const GWEI = 1000 * 1000 * 1000; +export const buildForkConfig = (): HardhatNetworkForkingUserConfig | undefined => { + let forkMode; + if (FORK) { + forkMode = { + url: NETWORKS_RPC_URL[FORK], + }; + if (FORK_BLOCK_NUMBER || BLOCK_TO_FORK[FORK]) { + forkMode.blockNumber = FORK_BLOCK_NUMBER || BLOCK_TO_FORK[FORK]; + } + } + return forkMode; +}; + export const NETWORKS_RPC_URL: iParamsPerNetwork = { [eEthereumNetwork.kovan]: ALCHEMY_KEY ? `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_KEY}` @@ -34,7 +52,7 @@ export const NETWORKS_RPC_URL: iParamsPerNetwork = { }; export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { - [eEthereumNetwork.kovan]: 65 * GWEI, + [eEthereumNetwork.kovan]: 1 * GWEI, [eEthereumNetwork.ropsten]: 65 * GWEI, [eEthereumNetwork.main]: 65 * GWEI, [eEthereumNetwork.coverage]: 65 * GWEI, @@ -42,6 +60,19 @@ export const NETWORKS_DEFAULT_GAS: iParamsPerNetwork = { [eEthereumNetwork.buidlerevm]: 65 * GWEI, [eEthereumNetwork.tenderlyMain]: 0.01 * GWEI, [ePolygonNetwork.mumbai]: 1 * GWEI, - [ePolygonNetwork.matic]: 2 * GWEI, + [ePolygonNetwork.matic]: 1 * GWEI, [eXDaiNetwork.xdai]: 1 * GWEI, }; + +export const BLOCK_TO_FORK: iParamsPerNetwork = { + [eEthereumNetwork.main]: 12406069, + [eEthereumNetwork.kovan]: undefined, + [eEthereumNetwork.ropsten]: undefined, + [eEthereumNetwork.coverage]: undefined, + [eEthereumNetwork.hardhat]: undefined, + [eEthereumNetwork.buidlerevm]: undefined, + [eEthereumNetwork.tenderlyMain]: 12406069, + [ePolygonNetwork.mumbai]: undefined, + [ePolygonNetwork.matic]: undefined, + [eXDaiNetwork.xdai]: undefined, +}; diff --git a/helpers/configuration.ts b/helpers/configuration.ts index 618eec82..82e74e41 100644 --- a/helpers/configuration.ts +++ b/helpers/configuration.ts @@ -6,7 +6,7 @@ import { ICommonConfiguration, eNetwork, } from './types'; -import { getParamPerPool } from './contracts-helpers'; +import { getEthersSignersAddresses, getParamPerPool } from './contracts-helpers'; import AaveConfig from '../markets/aave'; import MaticConfig from '../markets/matic'; import AmmConfig from '../markets/amm'; @@ -30,7 +30,7 @@ export const loadPoolConfig = (configName: ConfigNames): PoolConfiguration => { case ConfigNames.Matic: return MaticConfig; case ConfigNames.Amm: - return AmmConfig; + return AmmConfig; case ConfigNames.Commons: return CommonsConfig; default: @@ -61,14 +61,12 @@ export const getReservesConfigByPool = (pool: AavePools): iMultiPoolsAssets => { - const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; + const currentNetwork = process.env.FORK ? process.env.FORK : DRE.network.name; const targetAddress = getParamPerNetwork(config.PoolAdmin, currentNetwork); if (targetAddress) { return targetAddress; } - const addressList = await Promise.all( - (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) - ); + const addressList = await getEthersSignersAddresses(); const addressIndex = config.PoolAdminIndex; return addressList[addressIndex]; }; @@ -76,14 +74,12 @@ export const getGenesisPoolAdmin = async ( export const getEmergencyAdmin = async ( config: ICommonConfiguration ): Promise => { - const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; + const currentNetwork = process.env.FORK ? process.env.FORK : DRE.network.name; const targetAddress = getParamPerNetwork(config.EmergencyAdmin, currentNetwork); if (targetAddress) { return targetAddress; } - const addressList = await Promise.all( - (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) - ); + const addressList = await getEthersSignersAddresses(); const addressIndex = config.EmergencyAdminIndex; return addressList[addressIndex]; }; @@ -91,7 +87,7 @@ export const getEmergencyAdmin = async ( export const getTreasuryAddress = async ( config: ICommonConfiguration ): Promise => { - const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; + const currentNetwork = process.env.FORK ? process.env.FORK : DRE.network.name; return getParamPerNetwork(config.ReserveFactorTreasuryAddress, currentNetwork); }; @@ -101,7 +97,7 @@ export const getATokenDomainSeparatorPerNetwork = ( ): tEthereumAddress => getParamPerNetwork(config.ATokenDomainSeparator, network); export const getWethAddress = async (config: ICommonConfiguration) => { - const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; + const currentNetwork = process.env.FORK ? process.env.FORK : DRE.network.name; const wethAddress = getParamPerNetwork(config.WETH, currentNetwork); if (wethAddress) { return wethAddress; @@ -113,6 +109,19 @@ export const getWethAddress = async (config: ICommonConfiguration) => { return weth.address; }; +export const getWrappedNativeTokenAddress = async (config: ICommonConfiguration) => { + const currentNetwork = process.env.MAINNET_FORK === 'true' ? 'main' : DRE.network.name; + const wethAddress = getParamPerNetwork(config.WrappedNativeToken, currentNetwork); + if (wethAddress) { + return wethAddress; + } + if (currentNetwork.includes('main')) { + throw new Error('WETH not set at mainnet configuration.'); + } + const weth = await deployWETHMocked(); + return weth.address; +}; + export const getLendingRateOracles = (poolConfig: ICommonConfiguration) => { const { ProtocolGlobalParams: { UsdAddress }, @@ -120,8 +129,7 @@ export const getLendingRateOracles = (poolConfig: ICommonConfiguration) => { ReserveAssets, } = poolConfig; - const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; - const network = MAINNET_FORK ? 'main' : DRE.network.name; + const network = process.env.FORK ? process.env.FORK : DRE.network.name; return filterMapBy(LendingRateOracleRatesCommon, (key) => Object.keys(ReserveAssets[network]).includes(key) ); diff --git a/helpers/constants.ts b/helpers/constants.ts index 95e8922b..f2568ee0 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -15,6 +15,8 @@ export const oneEther = new BigNumber(Math.pow(10, 18)); export const oneRay = new BigNumber(Math.pow(10, 27)); export const MAX_UINT_AMOUNT = '115792089237316195423570985008687907853269984665640564039457584007913129639935'; +export const MAX_BORROW_CAP = '68719476735'; +export const MAX_SUPPLY_CAP = '68719476735'; export const ONE_YEAR = '31536000'; export const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; export const ONE_ADDRESS = '0x0000000000000000000000000000000000000001'; diff --git a/helpers/contracts-deployments.ts b/helpers/contracts-deployments.ts index 68024d2a..2d764885 100644 --- a/helpers/contracts-deployments.ts +++ b/helpers/contracts-deployments.ts @@ -56,6 +56,7 @@ import { linkBytecode, insertContractAddressInDb, deployContract, + verifyContract, } from './contracts-helpers'; import { StableAndVariableTokensHelperFactory } from '../types/StableAndVariableTokensHelperFactory'; import { MintableDelegationERC20 } from '../types/MintableDelegationERC20'; @@ -63,7 +64,6 @@ 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], @@ -73,7 +73,7 @@ export const deployUiPoolDataProvider = async ( const args: string[] = [incentivesController, aaveOracle]; const instance = await deployContract(id, args); if (verify) { - await verifyContract(instance.address, args); + await verifyContract(id, instance, args); } return instance; }; @@ -137,7 +137,9 @@ export const deployGenericLogic = async (reserveLogic: Contract, verify?: boolea linkedGenericLogicByteCode ); - const genericLogic = await (await genericLogicFactory.deploy()).deployed(); + const genericLogic = await ( + await genericLogicFactory.connect(await getFirstSigner()).deploy() + ).deployed(); return withSaveAndVerify(genericLogic, eContractid.GenericLogic, [], verify); }; @@ -158,7 +160,9 @@ export const deployValidationLogic = async ( linkedValidationLogicByteCode ); - const validationLogic = await (await validationLogicFactory.deploy()).deployed(); + const validationLogic = await ( + await validationLogicFactory.connect(await getFirstSigner()).deploy() + ).deployed(); return withSaveAndVerify(validationLogic, eContractid.ValidationLogic, [], verify); }; diff --git a/helpers/contracts-getters.ts b/helpers/contracts-getters.ts index 33da4054..89be0b9f 100644 --- a/helpers/contracts-getters.ts +++ b/helpers/contracts-getters.ts @@ -32,20 +32,20 @@ import { FlashLiquidationAdapterFactory, } from '../types'; import { IERC20DetailedFactory } from '../types/IERC20DetailedFactory'; -import { MockTokenMap } from './contracts-helpers'; -import { DRE, getDb } from './misc-utils'; +import { getEthersSigners, MockTokenMap } from './contracts-helpers'; +import { DRE, getDb, notFalsyOrZeroAddress } from './misc-utils'; import { eContractid, PoolConfiguration, tEthereumAddress, TokenContractId } from './types'; -export const getFirstSigner = async () => (await DRE.ethers.getSigners())[0]; +export const getFirstSigner = async () => (await getEthersSigners())[0]; -export const getLendingPoolAddressesProvider = async (address?: tEthereumAddress) => - await LendingPoolAddressesProviderFactory.connect( +export const getLendingPoolAddressesProvider = async (address?: tEthereumAddress) => { + return await LendingPoolAddressesProviderFactory.connect( address || (await getDb().get(`${eContractid.LendingPoolAddressesProvider}.${DRE.network.name}`).value()) .address, await getFirstSigner() ); - +}; export const getLendingPoolConfiguratorProxy = async (address?: tEthereumAddress) => { return await LendingPoolConfiguratorFactory.connect( address || @@ -172,7 +172,7 @@ export const getPairsTokenAggregator = ( }, aggregatorsAddresses: { [tokenSymbol: string]: tEthereumAddress } ): [string[], string[]] => { - const { ETH, USD, WETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; + const { ETH, WETH, ...assetsAddressesWithoutEth } = allAssetsAddresses; const pairs = Object.entries(assetsAddressesWithoutEth).map(([tokenSymbol, tokenAddress]) => { //if (true/*tokenSymbol !== 'WETH' && tokenSymbol !== 'ETH' && tokenSymbol !== 'LpWETH'*/) { @@ -195,12 +195,13 @@ export const getPairsTokenAggregator = ( export const getLendingPoolAddressesProviderRegistry = async (address?: tEthereumAddress) => await LendingPoolAddressesProviderRegistryFactory.connect( - address || - ( - await getDb() - .get(`${eContractid.LendingPoolAddressesProviderRegistry}.${DRE.network.name}`) - .value() - ).address, + notFalsyOrZeroAddress(address) + ? address + : ( + await getDb() + .get(`${eContractid.LendingPoolAddressesProviderRegistry}.${DRE.network.name}`) + .value() + ).address, await getFirstSigner() ); diff --git a/helpers/contracts-helpers.ts b/helpers/contracts-helpers.ts index 455dbb78..cb7c016e 100644 --- a/helpers/contracts-helpers.ts +++ b/helpers/contracts-helpers.ts @@ -22,16 +22,18 @@ import { 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'; +import { verifyEtherscanContract } from './etherscan-verification'; +import { getFirstSigner, getIErc20Detailed } from './contracts-getters'; +import { usingTenderly, verifyAtTenderly } from './tenderly-utils'; +import { usingPolygon, verifyAtPolygon } from './polygon-utils'; +import { getDefenderRelaySigner, usingDefender } from './defender-utils'; export type MockTokenMap = { [symbol: string]: MintableERC20 }; export const registerContractInJsonDb = async (contractId: string, contractInstance: Contract) => { const currentNetwork = DRE.network.name; - const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; - if (MAINNET_FORK || (currentNetwork !== 'hardhat' && !currentNetwork.includes('coverage'))) { + const FORK = process.env.FORK; + if (FORK || (currentNetwork !== 'hardhat' && !currentNetwork.includes('coverage'))) { console.log(`*** ${contractId} ***\n`); console.log(`Network: ${currentNetwork}`); console.log(`tx: ${contractInstance.deployTransaction.hash}`); @@ -65,11 +67,18 @@ export const rawInsertContractAddressInDb = async (id: string, address: tEthereu }) .write(); -export const getEthersSigners = async (): Promise => - await Promise.all(await DRE.ethers.getSigners()); +export const getEthersSigners = async (): Promise => { + const ethersSigners = await Promise.all(await DRE.ethers.getSigners()); + + if (usingDefender()) { + const [, ...users] = ethersSigners; + return [await getDefenderRelaySigner(), ...users]; + } + return ethersSigners; +}; export const getEthersSignersAddresses = async (): Promise => - await Promise.all((await DRE.ethers.getSigners()).map((signer) => signer.getAddress())); + await Promise.all((await getEthersSigners()).map((signer) => signer.getAddress())); export const getCurrentBlock = async () => { return DRE.ethers.provider.getBlockNumber(); @@ -82,9 +91,9 @@ export const deployContract = async ( contractName: string, args: any[] ): Promise => { - const contract = (await (await DRE.ethers.getContractFactory(contractName)).deploy( - ...args - )) as ContractType; + const contract = (await (await DRE.ethers.getContractFactory(contractName)) + .connect(await getFirstSigner()) + .deploy(...args)) as ContractType; await waitForTx(contract.deployTransaction); await registerContractInJsonDb(contractName, contract); return contract; @@ -98,18 +107,8 @@ export const withSaveAndVerify = async ( ): Promise => { await waitForTx(instance.deployTransaction); await registerContractInJsonDb(id, instance); - 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); + await verifyContract(id, instance, args); } return instance; }; @@ -153,9 +152,8 @@ export const getParamPerNetwork = (param: iParamsPerNetwork, network: eNet } = param as iEthereumParamsPerNetwork; const { matic, mumbai } = param as iPolygonParamsPerNetwork; const { xdai } = param as iXDaiParamsPerNetwork; - const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; - if (MAINNET_FORK) { - return main; + if (process.env.FORK) { + return param[process.env.FORK as eNetwork] as T; } switch (network) { @@ -328,3 +326,19 @@ export const buildFlashLiquidationAdapterParams = ( [collateralAsset, debtAsset, user, debtToCover, useEthPath] ); }; + +export const verifyContract = async ( + id: string, + instance: Contract, + args: (string | string[])[] +) => { + if (usingPolygon()) { + await verifyAtPolygon(id, instance, args); + } else { + if (usingTenderly()) { + await verifyAtTenderly(id, instance); + } + await verifyEtherscanContract(instance.address, args); + } + return instance; +}; diff --git a/helpers/defender-utils.ts b/helpers/defender-utils.ts new file mode 100644 index 00000000..8ce0075a --- /dev/null +++ b/helpers/defender-utils.ts @@ -0,0 +1,41 @@ +import { formatEther } from '@ethersproject/units'; +import { DefenderRelaySigner, DefenderRelayProvider } from 'defender-relay-client/lib/ethers'; +import { Signer } from 'ethers'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DRE, impersonateAccountsHardhat } from './misc-utils'; +import { usingTenderly } from './tenderly-utils'; + +export const usingDefender = () => process.env.DEFENDER === 'true'; + +export const getDefenderRelaySigner = async () => { + const { DEFENDER_API_KEY, DEFENDER_SECRET_KEY } = process.env; + let defenderSigner: Signer; + + if (!DEFENDER_API_KEY || !DEFENDER_SECRET_KEY) { + throw new Error('Defender secrets required'); + } + + const credentials = { apiKey: DEFENDER_API_KEY, apiSecret: DEFENDER_SECRET_KEY }; + + defenderSigner = new DefenderRelaySigner(credentials, new DefenderRelayProvider(credentials), { + speed: 'fast', + }); + + const defenderAddress = await defenderSigner.getAddress(); + console.log(' - Using Defender Relay: ', defenderAddress); + + // Replace signer if FORK=main is active + if (process.env.FORK === 'main') { + console.log(' - Impersonating Defender Relay'); + await impersonateAccountsHardhat([defenderAddress]); + defenderSigner = await (DRE as HardhatRuntimeEnvironment).ethers.getSigner(defenderAddress); + } + // Replace signer if Tenderly network is active + if (usingTenderly()) { + console.log(' - Impersonating Defender Relay via Tenderly'); + defenderSigner = await (DRE as HardhatRuntimeEnvironment).ethers.getSigner(defenderAddress); + } + console.log(' - Balance: ', formatEther(await defenderSigner.getBalance())); + + return defenderSigner; +}; diff --git a/helpers/etherscan-verification.ts b/helpers/etherscan-verification.ts index ddbf80e4..3bf097d3 100644 --- a/helpers/etherscan-verification.ts +++ b/helpers/etherscan-verification.ts @@ -20,7 +20,7 @@ function delay(ms: number) { return new Promise((resolve) => setTimeout(resolve, ms)); } -export const verifyContract = async ( +export const verifyEtherscanContract = async ( address: string, constructorArguments: (string | string[])[], libraries?: string diff --git a/helpers/init-helpers.ts b/helpers/init-helpers.ts index eb483420..678125a1 100644 --- a/helpers/init-helpers.ts +++ b/helpers/init-helpers.ts @@ -12,6 +12,7 @@ import { getAaveProtocolDataProvider, getAToken, getATokensAndRatesHelper, + getFirstSigner, getLendingPoolAddressesProvider, getLendingPoolConfiguratorProxy, getStableAndVariableTokensHelper, @@ -32,6 +33,7 @@ import { import { ZERO_ADDRESS } from './constants'; import { isZeroAddress } from 'ethereumjs-util'; import { DefaultReserveInterestRateStrategy, DelegationAwareAToken } from '../types'; +import { config } from 'process'; export const chooseATokenDeployment = (id: eContractid) => { switch (id) { @@ -144,6 +146,10 @@ export const initReservesByHelper = async ( ) as [string, IReserveParams][]; for (let [symbol, params] of reserves) { + if (!tokenAddresses[symbol]) { + console.log(`- Skipping init of ${symbol} due token address is not set at markets config`); + continue; + } const { strategy, aTokenImpl, reserveDecimals } = params; const { optimalUtilizationRate, @@ -201,7 +207,7 @@ export const initReservesByHelper = async ( interestRateStrategyAddress: strategyAddressPerAsset[reserveSymbols[i]], underlyingAsset: reserveTokens[i], treasury: treasuryAddress, - incentivesController: ZERO_ADDRESS, + incentivesController, underlyingAssetName: reserveSymbols[i], aTokenName: `${aTokenNamePrefix} ${reserveSymbols[i]}`, aTokenSymbol: `a${symbolPrefix}${reserveSymbols[i]}`, @@ -209,7 +215,7 @@ export const initReservesByHelper = async ( variableDebtTokenSymbol: `variableDebt${symbolPrefix}${reserveSymbols[i]}`, stableDebtTokenName: `${stableDebtTokenNamePrefix} ${reserveSymbols[i]}`, stableDebtTokenSymbol: `stableDebt${symbolPrefix}${reserveSymbols[i]}`, - params: '0x10' + params: '0x10', }); } @@ -271,11 +277,6 @@ export const configureReservesByHelper = async ( const atokenAndRatesDeployer = await getATokensAndRatesHelper(); const tokens: string[] = []; const symbols: string[] = []; - const baseLTVA: string[] = []; - const liquidationThresholds: string[] = []; - const liquidationBonuses: string[] = []; - const reserveFactors: string[] = []; - const stableRatesEnabled: boolean[] = []; const inputParams: { asset: string; @@ -283,7 +284,10 @@ export const configureReservesByHelper = async ( liquidationThreshold: BigNumberish; liquidationBonus: BigNumberish; reserveFactor: BigNumberish; + borrowCap: BigNumberish; + supplyCap: BigNumberish; stableBorrowingEnabled: boolean; + borrowingEnabled: boolean; }[] = []; for (const [ @@ -293,9 +297,18 @@ export const configureReservesByHelper = async ( liquidationBonus, liquidationThreshold, reserveFactor, + borrowCap, + supplyCap, stableBorrowRateEnabled, + borrowingEnabled, }, ] of Object.entries(reservesParams) as [string, IReserveParams][]) { + if (!tokenAddresses[assetSymbol]) { + console.log( + `- Skipping init of ${assetSymbol} due token address is not set at markets config` + ); + continue; + } if (baseLTVAsCollateral === '-1') continue; const assetAddressIndex = Object.keys(tokenAddresses).findIndex( @@ -317,19 +330,17 @@ export const configureReservesByHelper = async ( inputParams.push({ asset: tokenAddress, baseLTV: baseLTVAsCollateral, - liquidationThreshold: liquidationThreshold, - liquidationBonus: liquidationBonus, - reserveFactor: reserveFactor, + liquidationThreshold, + liquidationBonus, + reserveFactor, + borrowCap, + supplyCap, stableBorrowingEnabled: stableBorrowRateEnabled, + borrowingEnabled: borrowingEnabled, }); tokens.push(tokenAddress); symbols.push(assetSymbol); - baseLTVA.push(baseLTVAsCollateral); - liquidationThresholds.push(liquidationThreshold); - liquidationBonuses.push(liquidationBonus); - reserveFactors.push(reserveFactor); - stableRatesEnabled.push(stableBorrowRateEnabled); } if (tokens.length) { // Set aTokenAndRatesDeployer as temporal admin @@ -360,229 +371,6 @@ const getAddressById = async ( ): Promise => (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, - tokenAddresses: { [symbol: string]: tEthereumAddress }, - admin: tEthereumAddress, - addressesProviderAddress: tEthereumAddress, - ratesHelperAddress: tEthereumAddress, - dataProviderAddress: tEthereumAddress, - signer: Signer, - treasuryAddress: tEthereumAddress, - verify: boolean -) => { - let gasUsage = BigNumber.from('0'); - const atokenAndRatesDeployer = await (await getATokensAndRatesHelper(ratesHelperAddress)).connect( - signer - ); - - const addressProvider = await ( - await getLendingPoolAddressesProvider(addressesProviderAddress) - ).connect(signer); - const protocolDataProvider = await ( - await getAaveProtocolDataProvider(dataProviderAddress) - ).connect(signer); - const poolAddress = await addressProvider.getLendingPool(); - - // Set aTokenAndRatesDeployer as temporal admin - //await waitForTx(await addressProvider.setPoolAdmin(atokenAndRatesDeployer.address)); - - // CHUNK CONFIGURATION - const initChunks = 4; - - // 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[] = []; - - 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 eNetwork); - // Grab config from DB - for (const [symbol, address] of Object.entries(tokenAddresses)) { - const { aTokenAddress } = await protocolDataProvider.getReserveTokensAddresses(address); - const reserveParamIndex = Object.keys(reservesParams).findIndex((value) => value === symbol); - const [, { reserveDecimals: decimals }] = (Object.entries(reservesParams) as [ - string, - IReserveParams - ][])[reserveParamIndex]; - - if (!isZeroAddress(aTokenAddress)) { - console.log(`- Skipping ${symbol} due already initialized`); - continue; - } - 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}`, - ], - verify - ); - stableTokenImpl = stableDebt.address; - } - if (!variableTokenImpl) { - const variableDebt = await deployVariableDebtToken( - [ - poolAddress, - tokenAddresses[symbol], - ZERO_ADDRESS, // Incentives Controller - `Aave variable debt bearing ${symbol}`, - `variableDebt${symbol}`, - ], - verify - ); - variableTokenImpl = variableDebt.address; - } - if (!aTokenImplementation) { - const [, { aTokenImpl }] = (Object.entries(reservesParams) as [string, IReserveParams][])[ - reserveParamIndex - ]; - const deployCustomAToken = chooseATokenDeployment(aTokenImpl); - const aToken = await deployCustomAToken( - [ - poolAddress, - tokenAddresses[symbol], - treasuryAddress, - ZERO_ADDRESS, - `Aave interest bearing ${symbol}`, - `a${symbol}`, - ], - verify - ); - aTokenImplementation = aToken.address; - } - if (!strategyImpl) { - const [, { strategy }] = (Object.entries(reservesParams) as [string, IReserveParams][])[ - reserveParamIndex - ]; - const { - optimalUtilizationRate, - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, - } = strategy; - const rates = await deployDefaultReserveInterestRateStrategy( - [ - tokenAddresses[symbol], - optimalUtilizationRate, - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, - ], - verify - ); - strategyImpl = rates.address; - } - // --- 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); - } - - 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' - }); - } - - // 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 configurator.batchInitReserve(chunkedInitInputParams[chunkIndex]) - ); - - console.log(` - Reserve ready for: ${chunkedSymbols[chunkIndex].join(', ')}`); - console.log(' * gasUsed', tx3.gasUsed.toString()); - } - - // Set deployer back as admin - //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 diff --git a/helpers/misc-utils.ts b/helpers/misc-utils.ts index 54d5fa44..0315dfe0 100644 --- a/helpers/misc-utils.ts +++ b/helpers/misc-utils.ts @@ -115,3 +115,17 @@ export const notFalsyOrZeroAddress = (address: tEthereumAddress | null | undefin } return isAddress(address) && !isZeroAddress(address); }; + +export const impersonateAccountsHardhat = async (accounts: string[]) => { + if (process.env.TENDERLY === 'true') { + return; + } + // eslint-disable-next-line no-restricted-syntax + for (const account of accounts) { + // eslint-disable-next-line no-await-in-loop + await (DRE as HardhatRuntimeEnvironment).network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [account], + }); + } +}; diff --git a/helpers/oracles-helpers.ts b/helpers/oracles-helpers.ts index 6ec8827a..9fd2ba44 100644 --- a/helpers/oracles-helpers.ts +++ b/helpers/oracles-helpers.ts @@ -72,9 +72,6 @@ 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 ); diff --git a/helpers/polygon-utils.ts b/helpers/polygon-utils.ts new file mode 100644 index 00000000..555d2096 --- /dev/null +++ b/helpers/polygon-utils.ts @@ -0,0 +1,142 @@ +import axios from 'axios'; +import { Contract } from 'ethers/lib/ethers'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DRE } from './misc-utils'; +import { ePolygonNetwork, EthereumNetworkNames } from './types'; + +const TASK_FLATTEN_GET_FLATTENED_SOURCE = 'flatten:get-flattened-sources'; +const TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS = 'compile:solidity:get-source-paths'; + +/* Polygon Helpers */ + +export const usingPolygon = () => + DRE && Object.keys(ePolygonNetwork).includes((DRE as HardhatRuntimeEnvironment).network.name); + +/* Polygon Verifier */ + +const SOLIDITY_PRAGMA = 'pragma solidity'; +const LICENSE_IDENTIFIER = 'License-Identifier'; +const EXPERIMENTAL_ABIENCODER = 'pragma experimental ABIEncoderV2;'; + +const encodeDeployParams = (instance: Contract, args: (string | string[])[]) => { + return instance.interface.encodeDeploy(args).replace('0x', ''); +}; + +// Remove lines at "text" that includes "matcher" string, but keeping first "keep" lines +const removeLines = (text: string, matcher: string, keep = 0): string => { + let counter = keep; + return text + .split('\n') + .filter((line) => { + const match = !line.includes(matcher); + if (match === false && counter > 0) { + counter--; + return true; + } + return match; + }) + .join('\n'); +}; + +// Try to find the path of a Contract by name of the file without ".sol" +const findPath = async (id: string): Promise => { + const paths = await DRE.run(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS); + const path = paths.find((x) => { + const t = x.split('/'); + return t[t.length - 1].split('.')[0] == id; + }); + + if (!path) { + throw Error('Missing path for contract name: ${id}'); + } + + return path; +}; + +// Hardhat Flattener, similar to truffle flattener +const hardhatFlattener = async (filePath: string) => + await DRE.run(TASK_FLATTEN_GET_FLATTENED_SOURCE, { files: [filePath] }); + +// Verify a smart contract at Polygon Matic network via a GET request to the block explorer +export const verifyAtPolygon = async ( + id: string, + instance: Contract, + args: (string | string[])[] +) => { + /* + ${net == mumbai or mainnet} + https://explorer-${net}.maticvigil.com/api + ?module=contract + &action=verify + &addressHash={addressHash} + &name={name} + &compilerVersion={compilerVersion} + &optimization={false} + &contractSourceCode={contractSourceCode} + */ + const network = (DRE as HardhatRuntimeEnvironment).network.name; + const net = network === EthereumNetworkNames.matic ? 'mainnet' : network; + const filePath = await findPath(id); + const encodedConstructorParams = encodeDeployParams(instance, args); + const flattenSourceCode = await hardhatFlattener(filePath); + + // Remove pragmas and license identifier after first match, required by block explorers like explorer-mainnet.maticgivil.com or Etherscan + const cleanedSourceCode = removeLines( + removeLines(removeLines(flattenSourceCode, LICENSE_IDENTIFIER, 1), SOLIDITY_PRAGMA, 1), + EXPERIMENTAL_ABIENCODER, + 1 + ); + try { + console.log( + `[Polygon Verify] Verifying ${id} with address ${instance.address} at Matic ${net} network` + ); + const response = await axios.post( + `https://explorer-${net}.maticvigil.com/api`, + { + addressHash: instance.address, + name: id, + compilerVersion: 'v0.6.12+commit.27d51765', + optimization: 'true', + contractSourceCode: cleanedSourceCode, + constructorArguments: encodedConstructorParams, + }, + { + params: { + module: 'contract', + action: 'verify', + }, + headers: { + 'Content-Type': 'application/json', + Referer: 'aavematic-42e1f6da', + }, + } + ); + if (response.status === 200 && response.data.message === 'OK') { + console.log(`[Polygon Verify] Verified contract at Matic ${net} network.`); + console.log( + `[Polygon Verify] Check at: https://explorer-${net}.maticvigil.com/address/${instance.address}/contracts) \n` + ); + return; + } + + throw Error(JSON.stringify(response.data, null, 2)); + } catch (error) { + if (error?.message.includes('Smart-contract already verified.')) { + console.log( + `[Polygon Verify] Already verified. Check it at: https://explorer-${net}.maticvigil.com/address/${instance.address}/contracts) \n` + ); + return; + } + console.error('[Polygon Verify] Error:', error.toString()); + console.log( + `[Polygon Verify] Skipping verification for ${id} with ${instance.address} due an unknown error.` + ); + console.log( + `Please proceed with manual verification at https://explorer-${net}.maticvigil.com/address/${instance.address}/contracts` + ); + console.log(`- Use the following as encoded constructor params`); + console.log(encodedConstructorParams); + console.log(`- Flattened and cleaned source code`); + console.log(cleanedSourceCode); + } +}; diff --git a/helpers/tenderly-utils.ts b/helpers/tenderly-utils.ts index 27445608..7ef22252 100644 --- a/helpers/tenderly-utils.ts +++ b/helpers/tenderly-utils.ts @@ -1,3 +1,4 @@ +import { Contract } from 'ethers'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { DRE } from './misc-utils'; @@ -5,3 +6,12 @@ export const usingTenderly = () => DRE && ((DRE as HardhatRuntimeEnvironment).network.name.includes('tenderly') || process.env.TENDERLY === 'true'); + +export const verifyAtTenderly = async (id: string, instance: Contract) => { + console.log('\n- Doing Tenderly contract verification of', id); + await (DRE as any).tenderlyNetwork.verify({ + name: id, + address: instance.address, + }); + console.log(` - Verified ${id} at Tenderly!`); +}; diff --git a/helpers/types.ts b/helpers/types.ts index 8f6b19d2..0e0ac375 100644 --- a/helpers/types.ts +++ b/helpers/types.ts @@ -177,6 +177,13 @@ export enum ProtocolErrors { RC_INVALID_DECIMALS = '70', RC_INVALID_RESERVE_FACTOR = '71', LPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72', + VL_BORROW_CAP_EXCEEDED = '81', + RC_INVALID_BORROW_CAP = '82', + VL_SUPPLY_CAP_EXCEEDED = '83', + RC_INVALID_SUPPLY_CAP = '84', + LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN = '85', + VL_RESERVE_PAUSED = '86', + LPC_CALLER_NOT_RISK_OR_POOL_ADMIN = '87', // old @@ -296,7 +303,7 @@ export type iLpPoolAssets = Pick< export type iMaticPoolAssets = Pick< iAssetsWithoutUSD, - 'DAI' | 'USDC' | 'USDT' | 'WBTC' | 'WETH' | 'WMATIC' + 'DAI' | 'USDC' | 'USDT' | 'WBTC' | 'WETH' | 'WMATIC' | 'AAVE' >; export type iXDAIPoolAssets = Pick< @@ -350,12 +357,13 @@ export enum TokenContractId { BptBALWETH = 'BptBALWETH', WMATIC = 'WMATIC', STAKE = 'STAKE', - xSUSHI = 'xSUSHI' + xSUSHI = 'xSUSHI', } export interface IReserveParams extends IReserveBorrowParams, IReserveCollateralParams { aTokenImpl: eContractid; reserveFactor: string; + supplyCap: string; strategy: IInterestRateStrategyParams; } @@ -379,6 +387,7 @@ export interface IReserveBorrowParams { borrowingEnabled: boolean; stableBorrowRateEnabled: boolean; reserveDecimals: string; + borrowCap: string; } export interface IReserveCollateralParams { @@ -489,8 +498,10 @@ export interface ICommonConfiguration { ReservesConfig: iMultiPoolsAssets; ATokenDomainSeparator: iParamsPerNetwork; WETH: iParamsPerNetwork; + WrappedNativeToken: iParamsPerNetwork; WethGateway: iParamsPerNetwork; ReserveFactorTreasuryAddress: iParamsPerNetwork; + IncentivesController: iParamsPerNetwork; } export interface IAaveConfiguration extends ICommonConfiguration { diff --git a/markets/aave/commons.ts b/markets/aave/commons.ts index f16c9227..134e37eb 100644 --- a/markets/aave/commons.ts +++ b/markets/aave/commons.ts @@ -1,5 +1,11 @@ import BigNumber from 'bignumber.js'; -import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; +import { + oneEther, + oneRay, + RAY, + ZERO_ADDRESS, + MOCK_CHAINLINK_AGGREGATORS_PRICES, +} from '../../helpers/constants'; import { ICommonConfiguration, eEthereumNetwork } from '../../helpers/types'; // ---------------- @@ -87,6 +93,9 @@ export const CommonsConfig: ICommonConfiguration = { UNI: { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, + ENJ: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), + }, BUSD: { borrowRate: oneRay.multipliedBy(0.05).toFixed(), }, @@ -129,21 +138,21 @@ export const CommonsConfig: ICommonConfiguration = { ProviderRegistryOwner: { [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', [eEthereumNetwork.ropsten]: '', - [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.main]: '0xB9062896ec3A615a4e4444DF183F0531a77218AE', [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.tenderlyMain]: '0xB9062896ec3A615a4e4444DF183F0531a77218AE', }, LendingRateOracle: { [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]: '', @@ -175,7 +184,7 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '0xf99b8E67a0E044734B01EC4586D1c88C9a869718', + [eEthereumNetwork.kovan]: '', [eEthereumNetwork.ropsten]: '', [eEthereumNetwork.main]: '', [eEthereumNetwork.tenderlyMain]: '', @@ -193,9 +202,9 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.kovan]: '',//'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', + [eEthereumNetwork.kovan]: '', //'0xB8bE51E6563BB312Cbb2aa26e352516c25c26ac1', [eEthereumNetwork.ropsten]: ZERO_ADDRESS, - [eEthereumNetwork.main]: '',//'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', + [eEthereumNetwork.main]: '', //'0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', [eEthereumNetwork.tenderlyMain]: '0xA50ba011c48153De246E5192C8f9258A2ba79Ca9', }, FallbackOracle: { @@ -276,6 +285,7 @@ export const CommonsConfig: ICommonConfiguration = { YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + xSUSHI: '0x9b26214bEC078E68a394AaEbfbffF406Ce14893F', }, [eEthereumNetwork.tenderlyMain]: { AAVE: '0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012', @@ -298,6 +308,7 @@ export const CommonsConfig: ICommonConfiguration = { YFI: '0x7c5d4F8345e66f68099581Db340cd65B078C41f4', ZRX: '0x2Da4983a622a8498bb1a21FaE9D8F6C664939962', USD: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', + xSUSHI: '0x9b26214bEC078E68a394AaEbfbffF406Ce14893F', }, }, ReserveAssets: { @@ -331,6 +342,15 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', }, + WrappedNativeToken: { + [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', @@ -340,4 +360,13 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', }, + IncentivesController: { + [eEthereumNetwork.coverage]: ZERO_ADDRESS, + [eEthereumNetwork.hardhat]: ZERO_ADDRESS, + [eEthereumNetwork.buidlerevm]: ZERO_ADDRESS, + [eEthereumNetwork.kovan]: ZERO_ADDRESS, + [eEthereumNetwork.ropsten]: ZERO_ADDRESS, + [eEthereumNetwork.main]: ZERO_ADDRESS, + [eEthereumNetwork.tenderlyMain]: ZERO_ADDRESS, + }, }; diff --git a/markets/aave/index.ts b/markets/aave/index.ts index 9683dbe1..2ff2be79 100644 --- a/markets/aave/index.ts +++ b/markets/aave/index.ts @@ -23,6 +23,7 @@ import { strategyWETH, strategyYFI, strategyXSUSHI, + strategyENJ, } from './reservesConfigs'; // ---------------- @@ -38,7 +39,7 @@ export const AaveConfig: IAaveConfiguration = { BAT: strategyBAT, BUSD: strategyBUSD, DAI: strategyDAI, - ENJ: strategyREN, + ENJ: strategyENJ, KNC: strategyKNC, LINK: strategyLINK, MANA: strategyMANA, diff --git a/markets/aave/reservesConfigs.ts b/markets/aave/reservesConfigs.ts index a29e16d7..f44e4dc8 100644 --- a/markets/aave/reservesConfigs.ts +++ b/markets/aave/reservesConfigs.ts @@ -1,6 +1,6 @@ import { eContractid, IReserveParams } from '../../helpers/types'; -import { +import { rateStrategyStableOne, rateStrategyStableTwo, rateStrategyStableThree, @@ -21,7 +21,9 @@ export const strategyBUSD: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyDAI: IReserveParams = { @@ -33,7 +35,9 @@ export const strategyDAI: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategySUSD: IReserveParams = { @@ -45,7 +49,9 @@ export const strategySUSD: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyTUSD: IReserveParams = { @@ -57,7 +63,9 @@ export const strategyTUSD: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDC: IReserveParams = { @@ -69,7 +77,9 @@ export const strategyUSDC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDT: IReserveParams = { @@ -81,7 +91,9 @@ export const strategyUSDT: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyAAVE: IReserveParams = { @@ -93,7 +105,9 @@ export const strategyAAVE: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '0' + reserveFactor: '0', + borrowCap: '0', + supplyCap: '0', }; export const strategyBAT: IReserveParams = { @@ -105,7 +119,9 @@ export const strategyBAT: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyENJ: IReserveParams = { @@ -117,7 +133,9 @@ export const strategyENJ: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyWETH: IReserveParams = { @@ -129,7 +147,9 @@ export const strategyWETH: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyKNC: IReserveParams = { @@ -141,7 +161,9 @@ export const strategyKNC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyLINK: IReserveParams = { @@ -153,7 +175,9 @@ export const strategyLINK: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyMANA: IReserveParams = { @@ -165,7 +189,9 @@ export const strategyMANA: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '3500' + reserveFactor: '3500', + borrowCap: '0', + supplyCap: '0', }; export const strategyMKR: IReserveParams = { @@ -177,7 +203,9 @@ export const strategyMKR: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyREN: IReserveParams = { @@ -189,7 +217,9 @@ export const strategyREN: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategySNX: IReserveParams = { @@ -201,7 +231,9 @@ export const strategySNX: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '3500' + reserveFactor: '3500', + borrowCap: '0', + supplyCap: '0', }; // Invalid borrow rates in params currently, replaced with snx params @@ -214,7 +246,9 @@ export const strategyUNI: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.DelegationAwareAToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTC: IReserveParams = { @@ -226,7 +260,9 @@ export const strategyWBTC: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '8', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyYFI: IReserveParams = { @@ -238,7 +274,9 @@ export const strategyYFI: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyZRX: IReserveParams = { @@ -250,7 +288,9 @@ export const strategyZRX: IReserveParams = { stableBorrowRateEnabled: true, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyXSUSHI: IReserveParams = { @@ -263,4 +303,6 @@ export const strategyXSUSHI: IReserveParams = { reserveDecimals: '18', aTokenImpl: eContractid.AToken, reserveFactor: '3500', -}; \ No newline at end of file + borrowCap: '0', + supplyCap: '0', +}; diff --git a/markets/amm/commons.ts b/markets/amm/commons.ts index 3a676eda..8be1f2c0 100644 --- a/markets/amm/commons.ts +++ b/markets/amm/commons.ts @@ -139,14 +139,13 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.tenderlyMain]: '0x52D306e36E3B6B02c153d0266ff0f85d18BCD413', }, ProviderRegistryOwner: { - // DEPLOYED WITH CORRECT ADDRESS [eEthereumNetwork.kovan]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', [eEthereumNetwork.ropsten]: '', - [eEthereumNetwork.main]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.main]: '0xB9062896ec3A615a4e4444DF183F0531a77218AE', [eEthereumNetwork.coverage]: '', [eEthereumNetwork.hardhat]: '', [eEthereumNetwork.buidlerevm]: '', - [eEthereumNetwork.tenderlyMain]: '0xbd723fc4f1d737dcfc48a07fe7336766d34cad5f', + [eEthereumNetwork.tenderlyMain]: '0xB9062896ec3A615a4e4444DF183F0531a77218AE', }, LendingRateOracle: { [eEthereumNetwork.coverage]: '', @@ -326,6 +325,15 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', [eEthereumNetwork.tenderlyMain]: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', }, + WrappedNativeToken: { + [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', @@ -335,4 +343,13 @@ export const CommonsConfig: ICommonConfiguration = { [eEthereumNetwork.main]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', [eEthereumNetwork.tenderlyMain]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', }, + IncentivesController: { + [eEthereumNetwork.coverage]: ZERO_ADDRESS, + [eEthereumNetwork.hardhat]: ZERO_ADDRESS, + [eEthereumNetwork.buidlerevm]: ZERO_ADDRESS, + [eEthereumNetwork.kovan]: ZERO_ADDRESS, + [eEthereumNetwork.ropsten]: ZERO_ADDRESS, + [eEthereumNetwork.main]: ZERO_ADDRESS, + [eEthereumNetwork.tenderlyMain]: ZERO_ADDRESS, + }, }; diff --git a/markets/amm/reservesConfigs.ts b/markets/amm/reservesConfigs.ts index c92aa42f..d59f9ad6 100644 --- a/markets/amm/reservesConfigs.ts +++ b/markets/amm/reservesConfigs.ts @@ -1,10 +1,5 @@ -import { eContractid, IReserveParams} from '../../helpers/types'; -import { - rateStrategyAmmBase, - rateStrategyStable, - rateStrategyBaseOne, -} from './rateStrategies'; - +import { eContractid, IReserveParams } from '../../helpers/types'; +import { rateStrategyAmmBase, rateStrategyStable, rateStrategyBaseOne } from './rateStrategies'; export const strategyWETH: IReserveParams = { strategy: rateStrategyBaseOne, @@ -15,7 +10,9 @@ export const strategyWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTC: IReserveParams = { @@ -27,7 +24,9 @@ export const strategyWBTC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '8', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyDAI: IReserveParams = { @@ -39,7 +38,9 @@ export const strategyDAI: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDC: IReserveParams = { @@ -51,7 +52,9 @@ export const strategyUSDC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDT: IReserveParams = { @@ -63,7 +66,9 @@ export const strategyUSDT: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyDAIWETH: IReserveParams = { @@ -75,7 +80,9 @@ export const strategyDAIWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTCWETH: IReserveParams = { @@ -87,7 +94,9 @@ export const strategyWBTCWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategyAAVEWETH: IReserveParams = { @@ -99,7 +108,9 @@ export const strategyAAVEWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '500' + reserveFactor: '500', + borrowCap: '0', + supplyCap: '0', }; export const strategyBATWETH: IReserveParams = { @@ -111,7 +122,9 @@ export const strategyBATWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategyDAIUSDC: IReserveParams = { @@ -123,7 +136,9 @@ export const strategyDAIUSDC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyCRVWETH: IReserveParams = { @@ -135,7 +150,9 @@ export const strategyCRVWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategyLINKWETH: IReserveParams = { @@ -147,7 +164,9 @@ export const strategyLINKWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategyMKRWETH: IReserveParams = { @@ -159,7 +178,9 @@ export const strategyMKRWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategyRENWETH: IReserveParams = { @@ -171,7 +192,9 @@ export const strategyRENWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategySNXWETH: IReserveParams = { @@ -183,7 +206,9 @@ export const strategySNXWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyUNIWETH: IReserveParams = { @@ -195,7 +220,9 @@ export const strategyUNIWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDCWETH: IReserveParams = { @@ -207,7 +234,9 @@ export const strategyUSDCWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTCUSDC: IReserveParams = { @@ -219,7 +248,9 @@ export const strategyWBTCUSDC: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategyYFIWETH: IReserveParams = { @@ -231,7 +262,9 @@ export const strategyYFIWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', }; export const strategyBALWETH: IReserveParams = { @@ -243,5 +276,7 @@ export const strategyBALWETH: IReserveParams = { stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1500' -} \ No newline at end of file + reserveFactor: '1500', + borrowCap: '0', + supplyCap: '0', +}; diff --git a/markets/matic/commons.ts b/markets/matic/commons.ts index 42b269b0..8a0274a0 100644 --- a/markets/matic/commons.ts +++ b/markets/matic/commons.ts @@ -1,5 +1,11 @@ import BigNumber from 'bignumber.js'; -import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; +import { + oneEther, + oneRay, + RAY, + ZERO_ADDRESS, + MOCK_CHAINLINK_AGGREGATORS_PRICES, +} from '../../helpers/constants'; import { ICommonConfiguration, ePolygonNetwork } from '../../helpers/types'; // ---------------- @@ -49,7 +55,10 @@ export const CommonsConfig: ICommonConfiguration = { borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, WMATIC: { - borrowRate: oneRay.multipliedBy(0.05).toFixed(), // TEMP + borrowRate: oneRay.multipliedBy(0.05).toFixed(), + }, + AAVE: { + borrowRate: oneRay.multipliedBy(0.03).toFixed(), }, }, // ---------------- @@ -62,46 +71,46 @@ export const CommonsConfig: ICommonConfiguration = { [ePolygonNetwork.matic]: undefined, }, PoolAdminIndex: 0, + EmergencyAdminIndex: 0, EmergencyAdmin: { [ePolygonNetwork.mumbai]: undefined, [ePolygonNetwork.matic]: undefined, }, LendingPool: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '0xABdC61Cd16e5111f335f4135B7A0e65Cc7F86327', + [ePolygonNetwork.matic]: '', }, LendingPoolConfigurator: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '0x17c4A170FFF882862F656597889016D3a6073534', + [ePolygonNetwork.matic]: '', }, - EmergencyAdminIndex: 1, ProviderRegistry: { - [ePolygonNetwork.mumbai]: '0x569859d41499B4dDC28bfaA43915051FF0A38a6F', // TEMP - [ePolygonNetwork.matic]: '0x28334e4791860a0c1eCF89a62B973ba04a5d643F', // TEMP + [ePolygonNetwork.mumbai]: ZERO_ADDRESS, + [ePolygonNetwork.matic]: '0x3ac4e9aa29940770aeC38fe853a4bbabb2dA9C19', }, ProviderRegistryOwner: { - [ePolygonNetwork.mumbai]: '0x18d9bA2baEfBdE0FF137C4ad031427EF205f1Fd9', // TEMP - [ePolygonNetwork.matic]: '0x85e4A467343c0dc4aDAB74Af84448D9c45D8ae6F', // TEMP + [ePolygonNetwork.mumbai]: '', + [ePolygonNetwork.matic]: '0xD7D86236d6c463521920fCC50A9CB56f8C8Bf008', }, LendingRateOracle: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '', - }, + [ePolygonNetwork.matic]: '0x17F73aEaD876CC4059089ff815EDA37052960dFB', + }, LendingPoolCollateralManager: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '0x9Af76e0575D139570D3B4c821567Fe935E8c25C5', + [ePolygonNetwork.matic]: '', }, TokenDistributor: { [ePolygonNetwork.mumbai]: '', [ePolygonNetwork.matic]: '', }, - WethGateway: { + WethGateway: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '0x15A46f5073789b7D16F6F46632aE50Bae838d938', + [ePolygonNetwork.matic]: '', }, AaveOracle: { [ePolygonNetwork.mumbai]: '', - [ePolygonNetwork.matic]: '0x1B38fa90596F2C25bCf1B193A6c6a718349AFDfC', + [ePolygonNetwork.matic]: '0x0229F777B0fAb107F9591a41d5F02E4e98dB6f2d', }, FallbackOracle: { [ePolygonNetwork.mumbai]: ZERO_ADDRESS, @@ -109,12 +118,13 @@ export const CommonsConfig: ICommonConfiguration = { }, ChainlinkAggregator: { [ePolygonNetwork.matic]: { - DAI: '0x4746DeC9e833A82EC7C2C1356372CcF2cfcD2F3D', - USDC: '0xfE4A8cc5b5B2366C1B58Bea3858e81843581b2F7', - USDT: '0x0A6513e40db6EB1b165753AD52E80663aeA50545', - WBTC: '0xc907E116054Ad103354f2D350FD2514433D57F6f', - WETH: '0xF9680D99D6C9589e2a93a78A04A279e509205945', - WMATIC: '0xAB594600376Ec9fD91F8e885dADF0CE036862dE0', + AAVE: '0xbE23a3AA13038CfC28aFd0ECe4FdE379fE7fBfc4', + DAI: '0xFC539A559e170f848323e19dfD66007520510085', + USDC: '0xefb7e6be8356cCc6827799B6A7348eE674A80EaE', + USDT: '0xf9d5AAC6E5572AEFa6bd64108ff86a222F69B64d', + WBTC: '0xA338e0492B2F944E9F8C0653D3AD1484f2657a37', + WMATIC: '0x327e23A4855b6F663a28c5161541d69Af8973302', + USD: '0xF9680D99D6C9589e2a93a78A04A279e509205945', }, [ePolygonNetwork.mumbai]: { DAI: ZERO_ADDRESS, @@ -134,11 +144,19 @@ export const CommonsConfig: ICommonConfiguration = { [ePolygonNetwork.matic]: '', }, WETH: { - [ePolygonNetwork.mumbai]: '0x9c3C9283D3e44854697Cd22D3Faa240Cfb032889', // WMATIC address (untested) - [ePolygonNetwork.matic]: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', // WMATIC address + [ePolygonNetwork.mumbai]: ZERO_ADDRESS, + [ePolygonNetwork.matic]: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', + }, + WrappedNativeToken: { + [ePolygonNetwork.mumbai]: ZERO_ADDRESS, + [ePolygonNetwork.matic]: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', }, ReserveFactorTreasuryAddress: { - [ePolygonNetwork.mumbai]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP - [ePolygonNetwork.matic]: '0x464c71f6c2f760dda6093dcb91c24c39e5d6e18c', // TEMP + [ePolygonNetwork.mumbai]: ZERO_ADDRESS, + [ePolygonNetwork.matic]: '0x7734280A4337F37Fbf4651073Db7c28C80B339e9', + }, + IncentivesController: { + [ePolygonNetwork.mumbai]: ZERO_ADDRESS, + [ePolygonNetwork.matic]: '0x357D51124f59836DeD84c8a1730D72B749d8BC23', }, }; diff --git a/markets/matic/index.ts b/markets/matic/index.ts index cc1484ae..e5bb55bf 100644 --- a/markets/matic/index.ts +++ b/markets/matic/index.ts @@ -1,4 +1,3 @@ -import { oneRay, ZERO_ADDRESS } from '../../helpers/constants'; import { IMaticConfiguration, ePolygonNetwork } from '../../helpers/types'; import { CommonsConfig } from './commons'; @@ -9,6 +8,7 @@ import { strategyWBTC, strategyWETH, strategyMATIC, + strategyAAVE, } from './reservesConfigs'; // ---------------- @@ -18,7 +18,7 @@ import { export const MaticConfig: IMaticConfiguration = { ...CommonsConfig, MarketId: 'Matic Market', - ProviderId: 3, // Unknown? + ProviderId: 3, // Unknown? ReservesConfig: { DAI: strategyDAI, USDC: strategyUSDC, @@ -26,6 +26,7 @@ export const MaticConfig: IMaticConfiguration = { WBTC: strategyWBTC, WETH: strategyWETH, WMATIC: strategyMATIC, + AAVE: strategyAAVE, }, ReserveAssets: { [ePolygonNetwork.matic]: { @@ -35,8 +36,10 @@ export const MaticConfig: IMaticConfiguration = { WBTC: '0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6', WETH: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', WMATIC: '0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270', + AAVE: '0xD6DF932A45C0f255f85145f286eA0b292B21C90B', }, - [ePolygonNetwork.mumbai]: { // Mock tokens with a simple "mint" external function, except wmatic + [ePolygonNetwork.mumbai]: { + // Mock tokens with a simple "mint" external function, except wmatic DAI: '0x13b3fda609C1eeb23b4F4b69257840760dCa6C4a', USDC: '0x52b63223994433FdE2F1350Ba69Dfd2779f06ABA', USDT: '0xB3abd1912F586fDFFa13606882c28E27913853d2', diff --git a/markets/matic/reservesConfigs.ts b/markets/matic/reservesConfigs.ts index 608d028b..cbeba1a6 100644 --- a/markets/matic/reservesConfigs.ts +++ b/markets/matic/reservesConfigs.ts @@ -1,15 +1,13 @@ // import BigNumber from 'bignumber.js'; // import { oneRay } from '../../helpers/constants'; import { eContractid, IReserveParams } from '../../helpers/types'; -import { - rateStrategyStableOne, +import { rateStrategyStableTwo, rateStrategyStableThree, rateStrategyWETH, rateStrategyAAVE, rateStrategyVolatileOne, rateStrategyVolatileTwo, - rateStrategyVolatileThree, } from './rateStrategies'; export const strategyDAI: IReserveParams = { @@ -18,10 +16,12 @@ export const strategyDAI: IReserveParams = { liquidationThreshold: '8000', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDC: IReserveParams = { @@ -30,22 +30,26 @@ export const strategyUSDC: IReserveParams = { liquidationThreshold: '8500', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '6', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyUSDT: IReserveParams = { - strategy: rateStrategyStableThree, - baseLTVAsCollateral: '8000', - liquidationThreshold: '8500', - liquidationBonus: '10500', - borrowingEnabled: true, - stableBorrowRateEnabled: true, - reserveDecimals: '6', - aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + strategy: rateStrategyStableThree, + baseLTVAsCollateral: '0', + liquidationThreshold: '0', + liquidationBonus: '0', + borrowingEnabled: true, + stableBorrowRateEnabled: false, + reserveDecimals: '6', + aTokenImpl: eContractid.AToken, + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyWETH: IReserveParams = { @@ -54,10 +58,12 @@ export const strategyWETH: IReserveParams = { liquidationThreshold: '8250', liquidationBonus: '10500', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '1000' + reserveFactor: '1000', + borrowCap: '0', + supplyCap: '0', }; export const strategyWBTC: IReserveParams = { @@ -66,20 +72,38 @@ export const strategyWBTC: IReserveParams = { liquidationThreshold: '7500', liquidationBonus: '11000', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '8', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' + reserveFactor: '2000', + borrowCap: '0', + supplyCap: '0', }; export const strategyMATIC: IReserveParams = { - strategy: rateStrategyVolatileOne, //Temp? + strategy: rateStrategyVolatileOne, //Temp? baseLTVAsCollateral: '5000', liquidationThreshold: '6500', liquidationBonus: '11000', borrowingEnabled: true, - stableBorrowRateEnabled: true, + stableBorrowRateEnabled: false, reserveDecimals: '18', aTokenImpl: eContractid.AToken, - reserveFactor: '2000' -}; \ No newline at end of file + borrowCap: '0', + supplyCap: '0', + reserveFactor: '2000', +}; + +export const strategyAAVE: IReserveParams = { + strategy: rateStrategyAAVE, + baseLTVAsCollateral: '5000', + liquidationThreshold: '6500', + liquidationBonus: '11000', + borrowingEnabled: false, + stableBorrowRateEnabled: false, + reserveDecimals: '18', + aTokenImpl: eContractid.AToken, + borrowCap: '0', + supplyCap: '0', + reserveFactor: '0', +}; diff --git a/markets/xdai/commons.ts b/markets/xdai/commons.ts index 433d54ea..ee9f1f9f 100644 --- a/markets/xdai/commons.ts +++ b/markets/xdai/commons.ts @@ -1,5 +1,11 @@ import BigNumber from 'bignumber.js'; -import { oneEther, oneRay, RAY, ZERO_ADDRESS, MOCK_CHAINLINK_AGGREGATORS_PRICES } from '../../helpers/constants'; +import { + oneEther, + oneRay, + RAY, + ZERO_ADDRESS, + MOCK_CHAINLINK_AGGREGATORS_PRICES, +} from '../../helpers/constants'; import { ICommonConfiguration, eXDaiNetwork } from '../../helpers/types'; // ---------------- @@ -79,14 +85,14 @@ export const CommonsConfig: ICommonConfiguration = { }, LendingRateOracle: { [eXDaiNetwork.xdai]: '', - }, + }, LendingPoolCollateralManager: { [eXDaiNetwork.xdai]: '', }, TokenDistributor: { [eXDaiNetwork.xdai]: '', }, - WethGateway: { + WethGateway: { [eXDaiNetwork.xdai]: '', }, AaveOracle: { @@ -114,7 +120,13 @@ export const CommonsConfig: ICommonConfiguration = { WETH: { [eXDaiNetwork.xdai]: '', // DAI: xDAI is the base token, DAI is also there, We need WXDAI }, + WrappedNativeToken: { + [eXDaiNetwork.xdai]: '', // DAI: xDAI is the base token, DAI is also there, We need WXDAI + }, ReserveFactorTreasuryAddress: { - [eXDaiNetwork.xdai]: '', // TEMP + [eXDaiNetwork.xdai]: '', // TEMP + }, + IncentivesController: { + [eXDaiNetwork.xdai]: ZERO_ADDRESS, }, }; diff --git a/package-lock.json b/package-lock.json index 8310558b..ad482fe2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,18 +14,18 @@ } }, "@babel/helper-validator-identifier": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz", - "integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", "dev": true }, "@babel/highlight": { - "version": "7.13.10", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.13.10.tgz", - "integrity": "sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg==", + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.12.11", + "@babel/helper-validator-identifier": "^7.14.0", "chalk": "^2.0.0", "js-tokens": "^4.0.0" } @@ -278,9 +278,9 @@ } }, "@ethereum-waffle/ens": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.2.3.tgz", - "integrity": "sha512-OIfguJu4e+NYJHNnNVaFzvNG5WYPntWU1vnQuAFszBFytOeIkv2hAXv8RmRL+cledcvShtP3gmXU3Lvf0o4Sxw==", + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/ens/-/ens-3.2.4.tgz", + "integrity": "sha512-lkRVPCEkk7KOwH9MqFMB+gL0X8cZNsm+MnKpP9CNbAyhFos2sCDGcY8t6BA12KBK6pdMuuRXPxYL9WfPl9bqSQ==", "dev": true, "requires": { "@ensdomains/ens": "^0.4.4", @@ -299,14 +299,14 @@ } }, "@ethereum-waffle/provider": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.3.1.tgz", - "integrity": "sha512-I7iziCqvkVhfaYKRRjUoEK3JHne5PffLd8dokI9RvDighKn/OA4P8mMb400EGmuDG5NTVTM5hdnTa2jIYwrhyA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@ethereum-waffle/provider/-/provider-3.3.2.tgz", + "integrity": "sha512-ilz6cXK0ylSKCmZktTMpY4gjo0CN6rb86JfN7+RZYk6tKtZA6sXoOe95skWEQkGf1fZk7G817fTzLb0CmFDp1g==", "dev": true, "requires": { - "@ethereum-waffle/ens": "^3.2.2", + "@ethereum-waffle/ens": "^3.2.4", "ethers": "^5.0.1", - "ganache-core": "^2.10.2", + "ganache-core": "^2.13.2", "patch-package": "^6.2.2", "postinstall-postinstall": "^2.1.0" } @@ -1130,192 +1130,193 @@ } }, "@ethersproject/abi": { - "version": "5.0.13", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.0.13.tgz", - "integrity": "sha512-2coOH3D7ra1lwamKEH0HVc+Jbcsw5yfeCgmY8ekhCDualEiyyovD2qDcMBBcY3+kjoLHVTmo7ost6MNClxdOrg==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.1.2.tgz", + "integrity": "sha512-uMhoQVPX0UtfzTpekYQSEUcJGDgsJ25ifz+SV6PDETWaUFhcR8RNgb1QPTASP13inW8r6iy0/Xdq9D5hK2pNvA==", "dev": true, "requires": { - "@ethersproject/address": "^5.0.9", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/constants": "^5.0.8", - "@ethersproject/hash": "^5.0.10", - "@ethersproject/keccak256": "^5.0.7", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/strings": "^5.0.8" + "@ethersproject/address": "^5.1.0", + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/constants": "^5.1.0", + "@ethersproject/hash": "^5.1.0", + "@ethersproject/keccak256": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/strings": "^5.1.0" } }, "@ethersproject/abstract-provider": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.10.tgz", - "integrity": "sha512-OSReY5iz94iIaPlRvLiJP8YVIvQLx4aUvMMnHWSaA/vTU8QHZmgNlt4OBdYV1+aFY8Xl+VRYiWBHq72ZDKXXCQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.1.0.tgz", + "integrity": "sha512-8dJUnT8VNvPwWhYIau4dwp7qe1g+KgdRm4XTWvjkI9gAT2zZa90WF5ApdZ3vl1r6NDmnn6vUVvyphClRZRteTQ==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/networks": "^5.0.7", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/transactions": "^5.0.9", - "@ethersproject/web": "^5.0.12" + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/networks": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/transactions": "^5.1.0", + "@ethersproject/web": "^5.1.0" } }, "@ethersproject/abstract-signer": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.14.tgz", - "integrity": "sha512-JztBwVO7o5OHLh2vyjordlS4/1EjRyaECtc8vPdXTF1i4dXN+J0coeRoPN6ZFbBvi/YbaB6br2fvqhst1VQD/g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz", + "integrity": "sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w==", "dev": true, "requires": { - "@ethersproject/abstract-provider": "^5.0.8", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7" + "@ethersproject/abstract-provider": "^5.1.0", + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0" } }, "@ethersproject/address": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.11.tgz", - "integrity": "sha512-Et4GBdD8/tsBGjCEOKee9upN29qjL5kbRcmJifb4Penmiuh9GARXL2/xpXvEp5EW+EIW/rfCHFJrkYBgoQFQBw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.1.0.tgz", + "integrity": "sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/keccak256": "^5.0.7", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/rlp": "^5.0.7" + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/keccak256": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/rlp": "^5.1.0" } }, "@ethersproject/base64": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.9.tgz", - "integrity": "sha512-37RBz5LEZ9SlTNGiWCYFttnIN9J7qVs9Xo2EbqGqDH5LfW9EIji66S+YDMpXVo1zWDax1FkEldAoatxHK2gfgA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.1.0.tgz", + "integrity": "sha512-npD1bLvK4Bcxz+m4EMkx+F8Rd7CnqS9DYnhNu0/GlQBXhWjvfoAZzk5HJ0f1qeyp8d+A86PTuzLOGOXf4/CN8g==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9" + "@ethersproject/bytes": "^5.1.0" } }, "@ethersproject/basex": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.0.9.tgz", - "integrity": "sha512-FANswl1IN3PS0eltQxH2aM2+utPrkLUVG4XVFi6SafRG9EpAqXCgycxC8PU90mPGhigYTpg9cnTB5mCZ6ejQjw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.1.0.tgz", + "integrity": "sha512-vBKr39bum7DDbOvkr1Sj19bRMEPA4FnST6Utt6xhDzI7o7L6QNkDn2yrCfP+hnvJGhZFKtLygWwqlTBZoBXYLg==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/properties": "^5.0.7" + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/properties": "^5.1.0" } }, "@ethersproject/bignumber": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.15.tgz", - "integrity": "sha512-MTADqnyacvdRwtKh7o9ujwNDSM1SDJjYDMYAzjIgjoi9rh6TY4suMbhCa3i2vh3SUXiXSICyTI8ui+NPdrZ9Lw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.1.1.tgz", + "integrity": "sha512-AVz5iqz7+70RIqoQTznsdJ6DOVBYciNlvO+AlQmPTB6ofCvoihI9bQdr6wljsX+d5W7Yc4nyvQvP4JMzg0Agig==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0", "bn.js": "^4.4.0" } }, "@ethersproject/bytes": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.0.11.tgz", - "integrity": "sha512-D51plLYY5qF05AsoVQwIZVLqlBkaTPVHVP/1WmmBIWyHB0cRW0C9kh0kx5Exo51rB63Hk8PfHxc7SmpoaQFEyg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.1.0.tgz", + "integrity": "sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g==", "dev": true, "requires": { - "@ethersproject/logger": "^5.0.8" + "@ethersproject/logger": "^5.1.0" } }, "@ethersproject/constants": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.0.10.tgz", - "integrity": "sha512-OSo8jxkHLDXieCy8bgOFR7lMfgPxEzKvSDdP+WAWHCDM8+orwch0B6wzkTmiQFgryAtIctrBt5glAdJikZ3hGw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.1.0.tgz", + "integrity": "sha512-0/SuHrxc8R8k+JiLmJymxHJbojUDWBQqO+b+XFdwaP0jGzqC09YDy/CAlSZB6qHsBifY8X3I89HcK/oMqxRdBw==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.13" + "@ethersproject/bignumber": "^5.1.0" } }, "@ethersproject/contracts": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.0.12.tgz", - "integrity": "sha512-srijy31idjz8bE+gL1I6IRj2H4I9dUwfQ+QroLrIgNdGArqY8y2iFUKa3QTy+JBX26fJsdYiCQi1kKkaNpnMpQ==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.1.1.tgz", + "integrity": "sha512-6WwktLJ0DFWU8pDkgH4IGttQHhQN4SnwKFu9h+QYVe48VGWtbDu4W8/q/7QA1u/HWlWMrKxqawPiZUJj0UMvOw==", "dev": true, "requires": { - "@ethersproject/abi": "^5.0.10", - "@ethersproject/abstract-provider": "^5.0.8", - "@ethersproject/abstract-signer": "^5.0.10", - "@ethersproject/address": "^5.0.9", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/constants": "^5.0.8", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7" + "@ethersproject/abi": "^5.1.0", + "@ethersproject/abstract-provider": "^5.1.0", + "@ethersproject/abstract-signer": "^5.1.0", + "@ethersproject/address": "^5.1.0", + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/constants": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/transactions": "^5.1.0" } }, "@ethersproject/hash": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.0.12.tgz", - "integrity": "sha512-kn4QN+fhNFbUgX3XZTZUaQixi0oyfIEY+hfW+KtkHu+rq7dV76oAIvaLEEynu1/4npOL38E4X4YI42gGZk+C0Q==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.1.0.tgz", + "integrity": "sha512-fNwry20yLLPpnRRwm3fBL+2ksgO+KMadxM44WJmRIoTKzy4269+rbq9KFoe2LTqq2CXJM2CE70beGaNrpuqflQ==", "dev": true, "requires": { - "@ethersproject/abstract-signer": "^5.0.10", - "@ethersproject/address": "^5.0.9", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/keccak256": "^5.0.7", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/strings": "^5.0.8" + "@ethersproject/abstract-signer": "^5.1.0", + "@ethersproject/address": "^5.1.0", + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/keccak256": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/strings": "^5.1.0" } }, "@ethersproject/hdnode": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.0.10.tgz", - "integrity": "sha512-ZLwMtIcXK7xz2lSITDCl40W04CtRq4K9NwBxhCzdzPdaz6XnoJMwGz2YMVLg+8ksseq+RYtTwIIXtlK6vyvQyg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.1.0.tgz", + "integrity": "sha512-obIWdlujloExPHWJGmhJO/sETOOo7SEb6qemV4f8kyFoXg+cJK+Ta9SvBrj7hsUK85n3LZeZJZRjjM7oez3Clg==", "dev": true, "requires": { - "@ethersproject/abstract-signer": "^5.0.10", - "@ethersproject/basex": "^5.0.7", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/pbkdf2": "^5.0.7", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/sha2": "^5.0.7", - "@ethersproject/signing-key": "^5.0.8", - "@ethersproject/strings": "^5.0.8", - "@ethersproject/transactions": "^5.0.9", - "@ethersproject/wordlists": "^5.0.8" + "@ethersproject/abstract-signer": "^5.1.0", + "@ethersproject/basex": "^5.1.0", + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/pbkdf2": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/sha2": "^5.1.0", + "@ethersproject/signing-key": "^5.1.0", + "@ethersproject/strings": "^5.1.0", + "@ethersproject/transactions": "^5.1.0", + "@ethersproject/wordlists": "^5.1.0" } }, "@ethersproject/json-wallets": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.0.12.tgz", - "integrity": "sha512-nac553zGZnOewpjlqbfy7WBl8m3y7qudzRsI2dCxrediYtPIVIs9f6Pbnou8vDmmp8X4/U4W788d+Ma88o+Gbg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.1.0.tgz", + "integrity": "sha512-00n2iBy27w8zrGZSiU762UOVuzCQZxUZxopsZC47++js6xUFuI74DHcJ5K/2pddlF1YBskvmMuboEu1geK8mnA==", "dev": true, "requires": { - "@ethersproject/abstract-signer": "^5.0.10", - "@ethersproject/address": "^5.0.9", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/hdnode": "^5.0.8", - "@ethersproject/keccak256": "^5.0.7", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/pbkdf2": "^5.0.7", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/random": "^5.0.7", - "@ethersproject/strings": "^5.0.8", - "@ethersproject/transactions": "^5.0.9", + "@ethersproject/abstract-signer": "^5.1.0", + "@ethersproject/address": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/hdnode": "^5.1.0", + "@ethersproject/keccak256": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/pbkdf2": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/random": "^5.1.0", + "@ethersproject/strings": "^5.1.0", + "@ethersproject/transactions": "^5.1.0", "aes-js": "3.0.0", "scrypt-js": "3.0.1" } }, "@ethersproject/keccak256": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.0.9.tgz", - "integrity": "sha512-zhdUTj6RGtCJSgU+bDrWF6cGbvW453LoIC1DSNWrTlXzC7WuH4a+EiPrgc7/kNoRxerKuA/cxYlI8GwNtVtDlw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.1.0.tgz", + "integrity": "sha512-vrTB1W6AEYoadww5c9UyVJ2YcSiyIUTNDRccZIgwTmFFoSHwBtcvG1hqy9RzJ1T0bMdATbM9Hfx2mJ6H0i7Hig==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", + "@ethersproject/bytes": "^5.1.0", "js-sha3": "0.5.7" }, "dependencies": { @@ -1328,62 +1329,62 @@ } }, "@ethersproject/logger": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.0.10.tgz", - "integrity": "sha512-0y2T2NqykDrbPM3Zw9RSbPkDOxwChAL8detXaom76CfYoGxsOnRP/zTX8OUAV+x9LdwzgbWvWmeXrc0M7SuDZw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.1.0.tgz", + "integrity": "sha512-wtUaD1lBX10HBXjjKV9VHCBnTdUaKQnQ2XSET1ezglqLdPdllNOIlLfhyCRqXm5xwcjExVI5ETokOYfjPtaAlw==", "dev": true }, "@ethersproject/networks": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.9.tgz", - "integrity": "sha512-L8+VCQwArBLGkxZb/5Ns/OH/OxP38AcaveXIxhUTq+VWpXYjrObG3E7RDQIKkUx1S1IcQl/UWTz5w4DK0UitJg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.1.0.tgz", + "integrity": "sha512-A/NIrIED/G/IgU1XUukOA3WcFRxn2I4O5GxsYGA5nFlIi+UZWdGojs85I1VXkR1gX9eFnDXzjE6OtbgZHjFhIA==", "dev": true, "requires": { - "@ethersproject/logger": "^5.0.8" + "@ethersproject/logger": "^5.1.0" } }, "@ethersproject/pbkdf2": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.0.9.tgz", - "integrity": "sha512-ItE/wQ/WVw/ajEHPUVgfu0aEvksPgOQc+278bke8sGKnGO3ppjmqp0MHh17tHc1EBTzJbSms5aLIqc56qZ/oiA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.1.0.tgz", + "integrity": "sha512-B8cUbHHTgs8OtgJIafrRcz/YPDobVd5Ru8gTnShOiM9EBuFpYHQpq3+8iQJ6pyczDu6HP/oc/njAsIBhwFZYew==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/sha2": "^5.0.7" + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/sha2": "^5.1.0" } }, "@ethersproject/properties": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.9.tgz", - "integrity": "sha512-ZCjzbHYTw+rF1Pn8FDCEmx3gQttwIHcm/6Xee8g/M3Ga3SfW4tccNMbs5zqnBH0E4RoOPaeNgyg1O68TaF0tlg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.1.0.tgz", + "integrity": "sha512-519KKTwgmH42AQL3+GFV3SX6khYEfHsvI6v8HYejlkigSDuqttdgVygFTDsGlofNFchhDwuclrxQnD5B0YLNMg==", "dev": true, "requires": { - "@ethersproject/logger": "^5.0.8" + "@ethersproject/logger": "^5.1.0" } }, "@ethersproject/providers": { - "version": "5.0.24", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.0.24.tgz", - "integrity": "sha512-M4Iw1r4gGJkt7ZUa++iREuviKL/DIpmIMsaUlVlXtV+ZrUXeN8xQ3zOTrbz7R4h9W9oljBZM7i4D3Kn1krJ30A==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.1.2.tgz", + "integrity": "sha512-GqsS8rd+eyd4eNkcNgzZ4l9IRULBPUZa7JPnv22k4MHflMobUseyhfbVnmoN5bVNNkOxjV1IPTw9i0sV1hwdpg==", "dev": true, "requires": { - "@ethersproject/abstract-provider": "^5.0.8", - "@ethersproject/abstract-signer": "^5.0.10", - "@ethersproject/address": "^5.0.9", - "@ethersproject/basex": "^5.0.7", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/constants": "^5.0.8", - "@ethersproject/hash": "^5.0.10", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/networks": "^5.0.7", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/random": "^5.0.7", - "@ethersproject/rlp": "^5.0.7", - "@ethersproject/sha2": "^5.0.7", - "@ethersproject/strings": "^5.0.8", - "@ethersproject/transactions": "^5.0.9", - "@ethersproject/web": "^5.0.12", + "@ethersproject/abstract-provider": "^5.1.0", + "@ethersproject/abstract-signer": "^5.1.0", + "@ethersproject/address": "^5.1.0", + "@ethersproject/basex": "^5.1.0", + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/constants": "^5.1.0", + "@ethersproject/hash": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/networks": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/random": "^5.1.0", + "@ethersproject/rlp": "^5.1.0", + "@ethersproject/sha2": "^5.1.0", + "@ethersproject/strings": "^5.1.0", + "@ethersproject/transactions": "^5.1.0", + "@ethersproject/web": "^5.1.0", "bech32": "1.1.4", "ws": "7.2.3" }, @@ -1397,33 +1398,33 @@ } }, "@ethersproject/random": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.0.9.tgz", - "integrity": "sha512-DANG8THsKqFbJOantrxumtG6gyETNE54VfbsWa+SQAT8WKpDo9W/X5Zhh73KuhClaey1UI32uVmISZeq/Zxn1A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.1.0.tgz", + "integrity": "sha512-+uuczLQZ4+no9cP6TCoCktXx0u2YbNaRT7lRkSt12d8263e702f0u+4JnnRO8Qmv5nylWJebnqCHzyxP+6mLqw==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8" + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0" } }, "@ethersproject/rlp": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.0.9.tgz", - "integrity": "sha512-ns1U7ZMVeruUW6JXc4om+1w3w4ynHN/0fpwmeNTsAjwGKoF8SAUgue6ylKpHKWSti2idx7jDxbn8hNNFHk67CA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.1.0.tgz", + "integrity": "sha512-vDTyHIwNPrecy55gKGZ47eJZhBm8LLBxihzi5ou+zrSvYTpkSTWRcKUlXFDFQVwfWB+P5PGyERAdiDEI76clxw==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8" + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0" } }, "@ethersproject/sha2": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.0.9.tgz", - "integrity": "sha512-5FH4s47gM7N1fFAYQ1+m7aX0SbLg0Xr+6tvqndmNqc382/qBIbzXiGlUookrsjlPb6gLNurnTssCXjNM72J6lQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.1.0.tgz", + "integrity": "sha512-+fNSeZRstOpdRJpdGUkRONFCaiAqWkc91zXgg76Nlp5ndBQE25Kk5yK8gCPG1aGnCrbariiPr5j9DmrYH78JCA==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0", "hash.js": "1.1.3" }, "dependencies": { @@ -1440,116 +1441,117 @@ } }, "@ethersproject/signing-key": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.0.11.tgz", - "integrity": "sha512-Jfcru/BGwdkXhLxT+8WCZtFy7LL0TPFZw05FAb5asxB/MyVsEfNdNxGDtjVE9zXfmRSPe/EusXYY4K7wcygOyQ==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.1.0.tgz", + "integrity": "sha512-tE5LFlbmdObG8bY04NpuwPWSRPgEswfxweAI1sH7TbP0ml1elNfqcq7ii/3AvIN05i5U0Pkm3Tf8bramt8MmLw==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "bn.js": "^4.4.0", "elliptic": "6.5.4" } }, "@ethersproject/solidity": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.0.10.tgz", - "integrity": "sha512-8OG3HLqynWXDA6mVIHuHfF/ojTTwBahON7hc9GAKCqglzXCkVA3OpyxOJXPzjHClRIAUUiU7r9oy9Z/nsjtT/g==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.1.0.tgz", + "integrity": "sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/keccak256": "^5.0.7", - "@ethersproject/sha2": "^5.0.7", - "@ethersproject/strings": "^5.0.8" + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/keccak256": "^5.1.0", + "@ethersproject/sha2": "^5.1.0", + "@ethersproject/strings": "^5.1.0" } }, "@ethersproject/strings": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.0.10.tgz", - "integrity": "sha512-KAeoS1tZ9/5ECXiIZA6S6hywbD0so2VmuW+Wfyo5EDXeyZ6Na1nxTPhTnW7voQmjbeYJffCrOc0qLFJeylyg7w==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.1.0.tgz", + "integrity": "sha512-perBZy0RrmmL0ejiFGUOlBVjMsUceqLut3OBP3zP96LhiJWWbS8u1NqQVgN4/Gyrbziuda66DxiQocXhsvx+Sw==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/constants": "^5.0.8", - "@ethersproject/logger": "^5.0.8" + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/constants": "^5.1.0", + "@ethersproject/logger": "^5.1.0" } }, "@ethersproject/transactions": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.0.11.tgz", - "integrity": "sha512-ftsRvR9+gQp7L63F6+XmstvsZ4w8GtWvQB08e/zB+oB86Fnhq8+i/tkgpJplSHC8I/qgiCisva+M3u2GVhDFPA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.1.1.tgz", + "integrity": "sha512-Nwgbp09ttIVN0OoUBatCXaHxR7grWPHbozJN8v7AXDLrl6nnOIBEMDh+yJTnosSQlFhcyjfTGGN+Mx6R8HdvMw==", "dev": true, "requires": { - "@ethersproject/address": "^5.0.9", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/constants": "^5.0.8", - "@ethersproject/keccak256": "^5.0.7", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/rlp": "^5.0.7", - "@ethersproject/signing-key": "^5.0.8" + "@ethersproject/address": "^5.1.0", + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/constants": "^5.1.0", + "@ethersproject/keccak256": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/rlp": "^5.1.0", + "@ethersproject/signing-key": "^5.1.0" } }, "@ethersproject/units": { - "version": "5.0.11", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.0.11.tgz", - "integrity": "sha512-nOSPmcCWyB/dwoBRhhTtPGCsTbiXqmc7Q0Adwvafc432AC7hy3Fj3IFZtnSXsbtJ/GdHCIUIoA8gtvxSsFuBJg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.1.0.tgz", + "integrity": "sha512-isvJrx6qG0nKWfxsGORNjmOq/nh175fStfvRTA2xEKrGqx8JNJY83fswu4GkILowfriEM/eYpretfJnfzi7YhA==", "dev": true, "requires": { - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/constants": "^5.0.8", - "@ethersproject/logger": "^5.0.8" + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/constants": "^5.1.0", + "@ethersproject/logger": "^5.1.0" } }, "@ethersproject/wallet": { - "version": "5.0.12", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.0.12.tgz", - "integrity": "sha512-rboJebGf47/KPZrKZQdYg9BAYuXbc/OwcUyML1K1f2jnJeo1ObWV11U1PAWTjTbhhSy6/Fg+34GO2yMb5Dt1Rw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.1.0.tgz", + "integrity": "sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ==", "dev": true, "requires": { - "@ethersproject/abstract-provider": "^5.0.8", - "@ethersproject/abstract-signer": "^5.0.10", - "@ethersproject/address": "^5.0.9", - "@ethersproject/bignumber": "^5.0.13", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/hash": "^5.0.10", - "@ethersproject/hdnode": "^5.0.8", - "@ethersproject/json-wallets": "^5.0.10", - "@ethersproject/keccak256": "^5.0.7", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/random": "^5.0.7", - "@ethersproject/signing-key": "^5.0.8", - "@ethersproject/transactions": "^5.0.9", - "@ethersproject/wordlists": "^5.0.8" + "@ethersproject/abstract-provider": "^5.1.0", + "@ethersproject/abstract-signer": "^5.1.0", + "@ethersproject/address": "^5.1.0", + "@ethersproject/bignumber": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/hash": "^5.1.0", + "@ethersproject/hdnode": "^5.1.0", + "@ethersproject/json-wallets": "^5.1.0", + "@ethersproject/keccak256": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/random": "^5.1.0", + "@ethersproject/signing-key": "^5.1.0", + "@ethersproject/transactions": "^5.1.0", + "@ethersproject/wordlists": "^5.1.0" } }, "@ethersproject/web": { - "version": "5.0.14", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.14.tgz", - "integrity": "sha512-QpTgplslwZ0Sp9oKNLoRuS6TKxnkwfaEk3gr7zd7XLF8XBsYejsrQO/03fNfnMx/TAT/RR6WEw/mbOwpRSeVRA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.1.0.tgz", + "integrity": "sha512-LTeluWgTq04+RNqAkVhpydPcRZK/kKxD2Vy7PYGrAD27ABO9kTqTBKwiOuzTyAHKUQHfnvZbXmxBXJAGViSDcA==", "dev": true, "requires": { - "@ethersproject/base64": "^5.0.7", - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/strings": "^5.0.8" + "@ethersproject/base64": "^5.1.0", + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/strings": "^5.1.0" } }, "@ethersproject/wordlists": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.0.10.tgz", - "integrity": "sha512-jWsEm1iJzpg9SCXnNfFz+tcp4Ofzv0TJb6mj+soCNcar9GcT0yGz62ZsHC3pLQWaF4LkCzGwRJHJTXKjHQfG1A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.1.0.tgz", + "integrity": "sha512-NsUCi/TpBb+oTFvMSccUkJGtp5o/84eOyqp5q5aBeiNBSLkYyw21znRn9mAmxZgySpxgruVgKbaapnYPgvctPQ==", "dev": true, "requires": { - "@ethersproject/bytes": "^5.0.9", - "@ethersproject/hash": "^5.0.10", - "@ethersproject/logger": "^5.0.8", - "@ethersproject/properties": "^5.0.7", - "@ethersproject/strings": "^5.0.8" + "@ethersproject/bytes": "^5.1.0", + "@ethersproject/hash": "^5.1.0", + "@ethersproject/logger": "^5.1.0", + "@ethersproject/properties": "^5.1.0", + "@ethersproject/strings": "^5.1.0" } }, "@nodelib/fs.scandir": { @@ -1914,6 +1916,24 @@ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==", "dev": true }, + "@sinonjs/commons": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", + "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.0.5.tgz", + "integrity": "sha512-fUt6b15bjV/VW93UP5opNXJxdwZSbK1EdiwnhN7XrQrcpaOhMJpZ/CjwFpM3THpxwA+YviBUJKSuEqKlCK5alw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, "@solidity-parser/parser": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.5.2.tgz", @@ -1930,12 +1950,14 @@ } }, "@tenderly/hardhat-tenderly": { - "version": "1.1.0-beta.4", - "resolved": "https://registry.npmjs.org/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.1.0-beta.4.tgz", - "integrity": "sha512-B1KU0e+17KKstFLgyN1jy6ynNTZoHaVCy+1Wkx7WFnMJTfXQZEijmIyw48dLjUKvbaKWvgP7dE3VSoQnfKwo8g==", + "version": "1.1.0-beta.5", + "resolved": "https://registry.npmjs.org/@tenderly/hardhat-tenderly/-/hardhat-tenderly-1.1.0-beta.5.tgz", + "integrity": "sha512-NecF6ewefpDyIF/mz0kTZGlPMa+ri/LOAPPqmyRA/oGEZ19BLM0sHdJFObTv8kJnxIJZBHpTkUaeDPp8KcpZsg==", "dev": true, "requires": { - "axios": "^0.20.0", + "@nomiclabs/hardhat-ethers": "^2.0.1", + "axios": "^0.21.1", + "ethers": "^5.0.24", "fs-extra": "^9.0.1", "js-yaml": "^3.14.0" }, @@ -1981,15 +2003,15 @@ } }, "@truffle/error": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.12.tgz", - "integrity": "sha512-kZqqnPR9YDJG7KCDOcN1qH16Qs0oz1PzF0Y93AWdhXuL9S9HYo/RUUeqGKbPpRBEZldQUS8aa4EzfK08u5pu6g==", + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@truffle/error/-/error-0.0.14.tgz", + "integrity": "sha512-utJx+SZYoMqk8wldQG4gCVKhV8GwMJbWY7sLXFT/D8wWZTnE2peX7URFJh/cxkjTRCO328z1s2qewkhyVsu2HA==", "dev": true }, "@truffle/interface-adapter": { - "version": "0.4.21", - "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.4.21.tgz", - "integrity": "sha512-uGU9T0a1S1f1xiTrNksd9ba+55SyU9jaCLNauFGOtppWDmjHD7dorxncEyj7lM9dcKl+w8Y+wHy79bb/LG4XFQ==", + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/@truffle/interface-adapter/-/interface-adapter-0.4.23.tgz", + "integrity": "sha512-mfpwY25Apx36WHHNJMNHWyDQVFZoZYNQ43rOwr/n+5gAMxke7+D7+IR9UW4kuO/Jp0+2848UxMdRV+oqm017kQ==", "dev": true, "requires": { "bn.js": "^5.1.3", @@ -2088,13 +2110,13 @@ } }, "@truffle/provider": { - "version": "0.2.28", - "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.2.28.tgz", - "integrity": "sha512-lowQkQPVSnn1jG3JIrp5iTDxkHZErjjjbLsvpI1kd8sYQ5LcGorgPQVsGlhM5BfYUQCeHLeFwwFb0ghx3hisKw==", + "version": "0.2.30", + "resolved": "https://registry.npmjs.org/@truffle/provider/-/provider-0.2.30.tgz", + "integrity": "sha512-5ScTbWsrm7zmQjw020T41U30/kYA1LppXAtaeucUGN2jvPrSwlh0aTL18makbqftTx1NRuYKw7C8wO4jCKQSUQ==", "dev": true, "requires": { - "@truffle/error": "^0.0.12", - "@truffle/interface-adapter": "^0.4.21", + "@truffle/error": "^0.0.14", + "@truffle/interface-adapter": "^0.4.23", "web3": "1.3.5" } }, @@ -2191,9 +2213,9 @@ } }, "@types/lodash": { - "version": "4.14.168", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", - "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==", + "version": "4.14.169", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.169.tgz", + "integrity": "sha512-DvmZHoHTFJ8zhVYwCLWbQ7uAbYQEk52Ev2/ZiQ7Y7gQGeV9pjBqjnQpECMHfKS1rCYAhMI7LHVxwyZLZinJgdw==", "dev": true }, "@types/lowdb": { @@ -2212,9 +2234,9 @@ "dev": true }, "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", "dev": true }, "@types/mkdirp": { @@ -2239,9 +2261,9 @@ "dev": true }, "@types/node-fetch": { - "version": "2.5.8", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz", - "integrity": "sha512-fbjI6ja0N5ZA8TV53RUqzsKNkl9fv8Oj3T7zxW7FGv1GSH7gwJaNF8dzCjrqKaxKeUpTz4yT1DaJFq/omNpGfw==", + "version": "2.5.10", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.10.tgz", + "integrity": "sha512-IpkX0AasN44hgEad0gEF/V6EgR5n69VEqPEgnmoM8GsIGro3PowbWs4tR6IhxUTyPLpOn+fiGG6nrQhcmoCuIQ==", "dev": true, "requires": { "@types/node": "*", @@ -2298,21 +2320,21 @@ } }, "@types/secp256k1": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.1.tgz", - "integrity": "sha512-+ZjSA8ELlOp8SlKi0YLB2tz9d5iPNEmOBd+8Rz21wTMdaXQIa9b6TEnD6l5qKOCypE7FSyPyck12qZJxSDNoog==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.2.tgz", + "integrity": "sha512-QMg+9v0bbNJ2peLuHRWxzmy0HRJIG6gFZNhaRSp7S3ggSbCCxiqQB2/ybvhXyhHOCequpNkrx7OavNhrWOsW0A==", "dev": true, "requires": { "@types/node": "*" } }, "@types/sinon": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.11.tgz", - "integrity": "sha512-PwP4UY33SeeVKodNE37ZlOsR9cReypbMJOhZ7BVE0lB+Hix3efCOxiJWiE5Ia+yL9Cn2Ch72EjFTRze8RZsNtg==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.0.tgz", + "integrity": "sha512-jDZ55oCKxqlDmoTBBbBBEx+N8ZraUVhggMZ9T5t+6/Dh8/4NiOjSUfpLrPiEwxQDlAe3wpAkoXhWvE6LibtsMQ==", "dev": true, "requires": { - "@types/sinonjs__fake-timers": "*" + "@sinonjs/fake-timers": "^7.0.4" } }, "@types/sinon-chai": { @@ -2325,16 +2347,10 @@ "@types/sinon": "*" } }, - "@types/sinonjs__fake-timers": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", - "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", - "dev": true - }, "@types/underscore": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.0.tgz", - "integrity": "sha512-ipNAQLgRnG0EWN1cTtfdVHp5AyTW/PAMJ1PxLN4bAKSHbusSZbj48mIHiydQpN7GgQrYqwfnvZ573OVfJm5Nzg==", + "version": "1.11.2", + "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.2.tgz", + "integrity": "sha512-Ls2ylbo7++ITrWk2Yc3G/jijwSq5V3GT0tlgVXEl2kKYXY3ImrtmTCoE2uyTWFRI5owMBriloZFWbE1SXOsE7w==", "dev": true }, "@types/web3": { @@ -2434,6 +2450,38 @@ "uri-js": "^4.2.2" } }, + "amazon-cognito-identity-js": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-4.6.3.tgz", + "integrity": "sha512-MPVJfirbdmSGo7l4h7Kbn3ms1eJXT5Xq8ly+mCPPi8yAxaxdg7ouMUUNTqtDykoZxIdDLF/P6F3Zbg3dlGKOWg==", + "dev": true, + "requires": { + "buffer": "4.9.2", + "crypto-js": "^4.0.0", + "fast-base64-decode": "^1.0.0", + "isomorphic-unfetch": "^3.0.0", + "js-cookie": "^2.2.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, "amdefine": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", @@ -2448,12 +2496,12 @@ "dev": true }, "ansi-escapes": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", - "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, "requires": { - "type-fest": "^0.11.0" + "type-fest": "^0.21.3" } }, "ansi-regex": { @@ -2472,9 +2520,9 @@ } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -2649,18 +2697,23 @@ "dev": true }, "axios": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", - "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", "dev": true, "requires": { "follow-redirects": "^1.10.0" } }, + "axios-curlirize": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/axios-curlirize/-/axios-curlirize-1.3.7.tgz", + "integrity": "sha512-csSsuMyZj1dv1fL0zRPnDAHWrmlISMvK+wx9WJI/igRVDT4VMgbf2AVenaHghFLfI1nQijXUevYEguYV6u5hjA==" + }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "base-x": { "version": "3.0.8", @@ -3118,6 +3171,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, "requires": { "function-bind": "^1.1.1", "get-intrinsic": "^1.0.2" @@ -3540,9 +3594,9 @@ "dev": true }, "core-js-pure": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.9.1.tgz", - "integrity": "sha512-laz3Zx0avrw9a4QEIdmIblnVuJz8W51leY9iLThatCsFawWxC3sE4guASC78JbCin+DkwMpCdp1AVAuzL/GN7A==", + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.12.1.tgz", + "integrity": "sha512-1cch+qads4JnDSWsvc7d6nzlKAippwjUlf6vykkTLW53VSV+NkE6muGBToAjEA8pG90cSfcud3JgVmW2ds5TaQ==", "dev": true }, "core-util-is": { @@ -3687,6 +3741,12 @@ "randomfill": "^1.0.3" } }, + "crypto-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", + "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==", + "dev": true + }, "d": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", @@ -3882,6 +3942,101 @@ "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", "dev": true }, + "defender-base-client": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/defender-base-client/-/defender-base-client-1.7.0.tgz", + "integrity": "sha512-snNyKtxUZn8y0JewVAQDJUam1qESFnkJiOUNtutB07OzldUoA7R/n/xuu5LyM3z4ScvoXu6xeVe67xs2H60KKg==", + "dev": true, + "requires": { + "amazon-cognito-identity-js": "^4.3.3", + "axios": "^0.19.2", + "lodash": "^4.17.19", + "node-fetch": "^2.6.0" + }, + "dependencies": { + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "dev": true, + "requires": { + "follow-redirects": "1.5.10" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, + "requires": { + "debug": "=3.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "defender-relay-client": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/defender-relay-client/-/defender-relay-client-1.7.0.tgz", + "integrity": "sha512-NYHP0sW/IusDPMMxSxo7DG6mfTs6/up4AFhW5ww7l9uwszzxc5rhvCCfqHCeB9FrqkoX5G1DdDkHWHdSVwANVA==", + "dev": true, + "requires": { + "amazon-cognito-identity-js": "^4.3.3", + "axios": "^0.19.2", + "defender-base-client": "^1.7.0", + "lodash": "^4.17.19", + "node-fetch": "^2.6.0" + }, + "dependencies": { + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "dev": true, + "requires": { + "follow-redirects": "1.5.10" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, + "requires": { + "debug": "=3.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -4016,9 +4171,9 @@ "dev": true }, "dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", "dev": true }, "download": { @@ -4385,9 +4540,9 @@ }, "dependencies": { "@solidity-parser/parser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.0.tgz", - "integrity": "sha512-DT3f/Aa4tQysZwUsuqBwvr8YRJzKkvPUKV/9o2/o5EVw3xqlbzmtx4O60lTUcZdCawL+N8bBLNUyOGpHjGlJVQ==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.2.tgz", + "integrity": "sha512-d7VS7PxgMosm5NyaiyDJRNID5pK4AWj1l64Dbz0147hJgy5k2C0/ZiKK/9u5c5K+HRUVHmp+RMvGEjGh84oA5Q==", "dev": true }, "ethereumjs-util": { @@ -4885,41 +5040,41 @@ } }, "ethers": { - "version": "5.0.32", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.0.32.tgz", - "integrity": "sha512-rORfGWR0HsA4pjKMMcWZorw12DHsXqfIAuPVHJsXt+vI24jvXcVqx+rLsSvgOoLdaCMdxiN5qlIq2+4axKG31g==", + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.1.4.tgz", + "integrity": "sha512-EAPQ/fgGRu0PoR/VNFnHTMOtG/IZ0AItdW55C9T8ffmVu0rnyllZL404eBF66elJehOLz2kxnUrhXpE7TCpW7g==", "dev": true, "requires": { - "@ethersproject/abi": "5.0.13", - "@ethersproject/abstract-provider": "5.0.10", - "@ethersproject/abstract-signer": "5.0.14", - "@ethersproject/address": "5.0.11", - "@ethersproject/base64": "5.0.9", - "@ethersproject/basex": "5.0.9", - "@ethersproject/bignumber": "5.0.15", - "@ethersproject/bytes": "5.0.11", - "@ethersproject/constants": "5.0.10", - "@ethersproject/contracts": "5.0.12", - "@ethersproject/hash": "5.0.12", - "@ethersproject/hdnode": "5.0.10", - "@ethersproject/json-wallets": "5.0.12", - "@ethersproject/keccak256": "5.0.9", - "@ethersproject/logger": "5.0.10", - "@ethersproject/networks": "5.0.9", - "@ethersproject/pbkdf2": "5.0.9", - "@ethersproject/properties": "5.0.9", - "@ethersproject/providers": "5.0.24", - "@ethersproject/random": "5.0.9", - "@ethersproject/rlp": "5.0.9", - "@ethersproject/sha2": "5.0.9", - "@ethersproject/signing-key": "5.0.11", - "@ethersproject/solidity": "5.0.10", - "@ethersproject/strings": "5.0.10", - "@ethersproject/transactions": "5.0.11", - "@ethersproject/units": "5.0.11", - "@ethersproject/wallet": "5.0.12", - "@ethersproject/web": "5.0.14", - "@ethersproject/wordlists": "5.0.10" + "@ethersproject/abi": "5.1.2", + "@ethersproject/abstract-provider": "5.1.0", + "@ethersproject/abstract-signer": "5.1.0", + "@ethersproject/address": "5.1.0", + "@ethersproject/base64": "5.1.0", + "@ethersproject/basex": "5.1.0", + "@ethersproject/bignumber": "5.1.1", + "@ethersproject/bytes": "5.1.0", + "@ethersproject/constants": "5.1.0", + "@ethersproject/contracts": "5.1.1", + "@ethersproject/hash": "5.1.0", + "@ethersproject/hdnode": "5.1.0", + "@ethersproject/json-wallets": "5.1.0", + "@ethersproject/keccak256": "5.1.0", + "@ethersproject/logger": "5.1.0", + "@ethersproject/networks": "5.1.0", + "@ethersproject/pbkdf2": "5.1.0", + "@ethersproject/properties": "5.1.0", + "@ethersproject/providers": "5.1.2", + "@ethersproject/random": "5.1.0", + "@ethersproject/rlp": "5.1.0", + "@ethersproject/sha2": "5.1.0", + "@ethersproject/signing-key": "5.1.0", + "@ethersproject/solidity": "5.1.0", + "@ethersproject/strings": "5.1.0", + "@ethersproject/transactions": "5.1.1", + "@ethersproject/units": "5.1.0", + "@ethersproject/wallet": "5.1.0", + "@ethersproject/web": "5.1.0", + "@ethersproject/wordlists": "5.1.0" } }, "ethjs-unit": { @@ -5189,6 +5344,12 @@ "checkpoint-store": "^1.1.0" } }, + "fast-base64-decode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz", + "integrity": "sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==", + "dev": true + }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5379,9 +5540,9 @@ "dev": true }, "follow-redirects": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.3.tgz", - "integrity": "sha512-DUgl6+HDzB0iEptNQEXLx/KhTmDb8tZUHSeLqpnjpknR70H0nC2t9N73BK6fN4hOvJ84pKlIQVQ4k5FFlBedKA==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", "dev": true }, "for-each": { @@ -5529,7 +5690,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", @@ -6368,6 +6530,36 @@ "@ethersproject/strings": ">=5.0.0-beta.130" } }, + "@ethersproject/abstract-provider": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.0.8.tgz", + "integrity": "sha512-fqJXkewcGdi8LogKMgRyzc/Ls2js07yor7+g9KfPs09uPOcQLg7cc34JN+lk34HH9gg2HU0DIA5797ZR8znkfw==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/networks": "^5.0.7", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/transactions": "^5.0.9", + "@ethersproject/web": "^5.0.12" + } + }, + "@ethersproject/abstract-signer": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.0.10.tgz", + "integrity": "sha512-irx7kH7FDAeW7QChDPW19WsxqeB1d3XLyOLSXm0bfPqL1SS07LXWltBJUBUxqC03ORpAOcM3JQj57DU8JnVY2g==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/abstract-provider": "^5.0.8", + "@ethersproject/bignumber": "^5.0.13", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7" + } + }, "@ethersproject/address": { "version": "5.0.9", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.0.9.tgz", @@ -6382,6 +6574,16 @@ "@ethersproject/rlp": "^5.0.7" } }, + "@ethersproject/base64": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.0.7.tgz", + "integrity": "sha512-S5oh5DVfCo06xwJXT8fQC68mvJfgScTl2AXvbYMsHNfIBTDb084Wx4iA9MNlEReOv6HulkS+gyrUM/j3514rSw==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/bytes": "^5.0.9" + } + }, "@ethersproject/bignumber": { "version": "5.0.13", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.0.13.tgz", @@ -6449,6 +6651,16 @@ "dev": true, "optional": true }, + "@ethersproject/networks": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.0.7.tgz", + "integrity": "sha512-dI14QATndIcUgcCBL1c5vUr/YsI5cCHLN81rF7PU+yS7Xgp2/Rzbr9+YqpC6NBXHFUASjh6GpKqsVMpufAL0BQ==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/logger": "^5.0.8" + } + }, "@ethersproject/properties": { "version": "5.0.7", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.0.7.tgz", @@ -6513,6 +6725,20 @@ "@ethersproject/signing-key": "^5.0.8" } }, + "@ethersproject/web": { + "version": "5.0.12", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.0.12.tgz", + "integrity": "sha512-gVxS5iW0bgidZ76kr7LsTxj4uzN5XpCLzvZrLp8TP+4YgxHfCeetFyQkRPgBEAJdNrexdSBayvyJvzGvOq0O8g==", + "dev": true, + "optional": true, + "requires": { + "@ethersproject/base64": "^5.0.7", + "@ethersproject/bytes": "^5.0.9", + "@ethersproject/logger": "^5.0.8", + "@ethersproject/properties": "^5.0.7", + "@ethersproject/strings": "^5.0.8" + } + }, "@sindresorhus/is": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", @@ -7712,9 +7938,9 @@ }, "dependencies": { "bn.js": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", - "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", "dev": true, "optional": true } @@ -7825,14 +8051,6 @@ "dev": true, "requires": { "node-gyp-build": "^4.2.0" - }, - "dependencies": { - "node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", - "dev": true - } } }, "bytes": { @@ -7933,6 +8151,16 @@ } } }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, "caniuse-lite": { "version": "1.0.30001174", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001174.tgz", @@ -8451,6 +8679,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -8676,6 +8905,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -10845,7 +11075,8 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "functional-red-black-tree": { "version": "1.0.1", @@ -10853,6 +11084,17 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "get-intrinsic": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", + "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -10968,6 +11210,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -11005,7 +11248,8 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true }, "has-to-string-tag-x": { "version": "1.4.1", @@ -11278,7 +11522,8 @@ "is-callable": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==" + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "dev": true }, "is-ci": { "version": "2.0.0", @@ -11301,7 +11546,8 @@ "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true }, "is-descriptor": { "version": "1.0.2", @@ -11350,7 +11596,8 @@ "is-negative-zero": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", - "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==" + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true }, "is-object": { "version": "1.0.2", @@ -11379,6 +11626,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -11394,6 +11642,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -12236,7 +12485,8 @@ "object-inspect": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==" + "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "dev": true }, "object-is": { "version": "1.1.4", @@ -12246,33 +12496,13 @@ "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } } }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object-visit": { "version": "1.0.1", @@ -12287,32 +12517,12 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3", "has-symbols": "^1.0.1", "object-keys": "^1.1.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } } }, "object.getownpropertydescriptors": { @@ -12844,71 +13054,22 @@ }, "dependencies": { "es-abstract": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0.tgz", - "integrity": "sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw==", + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", + "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", "dev": true, "requires": { - "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", - "get-intrinsic": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.2", - "is-callable": "^1.2.3", - "is-negative-zero": "^2.0.1", - "is-regex": "^1.1.2", - "is-string": "^1.0.5", - "object-inspect": "^1.9.0", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.2", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.2", - "string.prototype.trimend": "^1.0.4", - "string.prototype.trimstart": "^1.0.4", - "unbox-primitive": "^1.0.0" - }, - "dependencies": { - "has-symbols": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", - "dev": true - }, - "is-callable": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", - "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", - "dev": true - }, - "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" - } - }, - "string.prototype.trimend": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", - "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - }, - "string.prototype.trimstart": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", - "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" - } - } + "object.assign": "^4.1.1", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } } } @@ -12996,15 +13157,6 @@ "uuid": "^3.3.2" } }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -13663,34 +13815,13 @@ "call-bind": "^1.0.0", "define-properties": "^1.1.3", "es-abstract": "^1.18.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } } }, "string.prototype.trimend": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz", "integrity": "sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw==", + "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" @@ -13700,6 +13831,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz", "integrity": "sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg==", + "dev": true, "requires": { "call-bind": "^1.0.0", "define-properties": "^1.1.3" @@ -13886,6 +14018,15 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", "dev": true + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } } } }, @@ -14247,14 +14388,6 @@ "dev": true, "requires": { "node-gyp-build": "^4.2.0" - }, - "dependencies": { - "node-gyp-build": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz", - "integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg==", - "dev": true - } } }, "utf8": { @@ -15233,6 +15366,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", @@ -15280,9 +15414,9 @@ } }, "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -15421,9 +15555,9 @@ } }, "hardhat": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.2.1.tgz", - "integrity": "sha512-8s7MtGXdh0NDwQKdlA8m8QdloVIN1+hv5aFpn0G5Ljj9vfNY9kUoc0a9pMboeGbd9WrS+XrZs5YlsPgQjaW/Tg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.3.0.tgz", + "integrity": "sha512-nc4ro2bM4wPaA6/0Y22o5F5QrifQk2KCyPUUKLPUeFFZoGNGYB8vmeW/k9gV9DdMukdWTzfYlKc2Jn4bfb6tDQ==", "dev": true, "requires": { "@ethereumjs/block": "^3.2.1", @@ -15789,6 +15923,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -15814,7 +15949,8 @@ "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", - "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==" + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true }, "has-to-string-tag-x": { "version": "1.4.1", @@ -15864,9 +16000,9 @@ } }, "hosted-git-info": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", - "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "http-basic": { @@ -15916,9 +16052,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.55", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.55.tgz", - "integrity": "sha512-koZJ89uLZufDvToeWO5BrC4CR4OUfHnUz2qoPs/daQH6qq3IN62QFxCTZ+bKaCE0xaoCAJYE4AXre8AbghCrhg==", + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", "dev": true } } @@ -15972,9 +16108,9 @@ } }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -16146,9 +16282,9 @@ "dev": true }, "is-bigint": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.1.tgz", - "integrity": "sha512-J0ELF4yHFxHy0cmSxZuheDOz2luOdVvqjwmEcj8H/L1JHeuEDSDbeRP+Dk9kFVk5RTFzbucJ2Kb9F7ixY2QaCg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", "dev": true }, "is-binary-path": { @@ -16161,12 +16297,12 @@ } }, "is-boolean-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.0.tgz", - "integrity": "sha512-a7Uprx8UtD+HWdyYwnD1+ExtTgqQtD2k/1yJgtXP6wnMm8byhkoTZRl+95LLThpzNZJ5aEvi46cdH+ayMFRwmA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", "dev": true, "requires": { - "call-bind": "^1.0.0" + "call-bind": "^1.0.2" } }, "is-buffer": { @@ -16191,24 +16327,24 @@ } }, "is-core-module": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz", - "integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", "dev": true, "requires": { "has": "^1.0.3" } }, "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", "dev": true }, "is-docker": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", - "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true }, "is-extglob": { @@ -16230,9 +16366,9 @@ "dev": true }, "is-generator-function": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.8.tgz", - "integrity": "sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.9.tgz", + "integrity": "sha512-ZJ34p1uvIfptHCN7sFTjGibB9/oBg17sHqzDLfuwhvmN/qLVvIQXRQ8licZQ35WJ8KuEQt/etnnzQFI9C9Ue/A==", "dev": true }, "is-glob": { @@ -16279,9 +16415,9 @@ "dev": true }, "is-number-object": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", - "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", "dev": true }, "is-object": { @@ -16312,13 +16448,13 @@ "dev": true }, "is-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", - "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", "dev": true, "requires": { "call-bind": "^1.0.2", - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "is-retry-allowed": { @@ -16334,18 +16470,18 @@ "dev": true }, "is-string": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", - "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", "dev": true }, "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "requires": { - "has-symbols": "^1.0.1" + "has-symbols": "^1.0.2" } }, "is-typed-array": { @@ -16400,6 +16536,16 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "isomorphic-unfetch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz", + "integrity": "sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==", + "dev": true, + "requires": { + "node-fetch": "^2.6.1", + "unfetch": "^4.2.0" + } + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -16422,6 +16568,12 @@ "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", "dev": true }, + "js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", + "dev": true + }, "js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -16988,9 +17140,9 @@ "dev": true }, "mcl-wasm": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.6.tgz", - "integrity": "sha512-cbRl3sUOkBeRY2hsM4t1EIln2TIdQBkSiTOqNTv/4Hu5KOECnMWCgjIf+a9Ebunyn22VKqkMF3zj6ejRzz7YBw==", + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.7.tgz", + "integrity": "sha512-jDGiCQA++5hX37gdH6RDZ3ZsA0raet7xyY/R5itj5cbcdf4Gvw+YyxWX/ZZ0Z2UPxJiw1ktRsCJZzpnqlQILdw==", "dev": true }, "md5.js": { @@ -17173,13 +17325,13 @@ "dev": true }, "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", "dev": true, "requires": { "braces": "^3.0.1", - "picomatch": "^2.0.5" + "picomatch": "^2.2.3" } }, "miller-rabin": { @@ -17199,18 +17351,18 @@ "dev": true }, "mime-db": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.46.0.tgz", - "integrity": "sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ==", + "version": "1.47.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz", + "integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==", "dev": true }, "mime-types": { - "version": "2.1.29", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.29.tgz", - "integrity": "sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ==", + "version": "2.1.30", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz", + "integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==", "dev": true, "requires": { - "mime-db": "1.46.0" + "mime-db": "1.47.0" } }, "mimic-fn": { @@ -17758,9 +17910,9 @@ "dev": true }, "object-inspect": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.9.0.tgz", - "integrity": "sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==", + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", "dev": true }, "object-keys": { @@ -18115,9 +18267,9 @@ "dev": true }, "pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", "dev": true, "requires": { "create-hash": "^1.1.2", @@ -18140,9 +18292,9 @@ "dev": true }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", "dev": true }, "pify": { @@ -18248,31 +18400,31 @@ "dev": true }, "prettier": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.2.1.tgz", - "integrity": "sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", + "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", "dev": true }, "prettier-plugin-solidity": { - "version": "1.0.0-beta.6", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.6.tgz", - "integrity": "sha512-WymLqd22Hl93t5+HDNLk08TAWp4i4vZMhpihuVqkwOApjCT7mH1qwhLtvf3m+NdU//qj8vrPDmMoT+xc74skcg==", + "version": "1.0.0-beta.10", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-beta.10.tgz", + "integrity": "sha512-55UsEbeJfqYKB3RFR7Nvpi+ApEoUfgdKHVg2ZybrbOkRW4RTblyONLL3mEr8Vrxpo7wBbObVLbWodGg4YXIQ7g==", "dev": true, "requires": { - "@solidity-parser/parser": "^0.12.0", + "@solidity-parser/parser": "^0.12.1", "dir-to-object": "^2.0.0", - "emoji-regex": "^9.2.1", + "emoji-regex": "^9.2.2", "escape-string-regexp": "^4.0.0", "prettier": "^2.2.1", - "semver": "^7.3.4", - "solidity-comments-extractor": "^0.0.4", - "string-width": "^4.2.0" + "semver": "^7.3.5", + "solidity-comments-extractor": "^0.0.7", + "string-width": "^4.2.2" }, "dependencies": { "@solidity-parser/parser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.0.tgz", - "integrity": "sha512-DT3f/Aa4tQysZwUsuqBwvr8YRJzKkvPUKV/9o2/o5EVw3xqlbzmtx4O60lTUcZdCawL+N8bBLNUyOGpHjGlJVQ==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.2.tgz", + "integrity": "sha512-d7VS7PxgMosm5NyaiyDJRNID5pK4AWj1l64Dbz0147hJgy5k2C0/ZiKK/9u5c5K+HRUVHmp+RMvGEjGh84oA5Q==", "dev": true }, "ansi-regex": { @@ -18309,9 +18461,9 @@ } }, "semver": { - "version": "7.3.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", - "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -19201,9 +19353,9 @@ } }, "solidity-comments-extractor": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.4.tgz", - "integrity": "sha512-58glBODwXIKMaQ7rfcJOrWtFQMMOK28tJ0/LcB5Xhu7WtAxk4UX2fpgKPuaL41XjMp/y0gAa1MTLqk018wuSzA==", + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", + "integrity": "sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==", "dev": true }, "solidity-coverage": { @@ -19234,9 +19386,9 @@ }, "dependencies": { "@solidity-parser/parser": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.1.tgz", - "integrity": "sha512-ikxVpwskNxEp2fvYS1BdRImnevHmM97zdPFBa1cVtjtNpoqCm/EmljATTZk0s9G/zsN5ZbPf9OAIAW4gbBJiRA==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.12.2.tgz", + "integrity": "sha512-d7VS7PxgMosm5NyaiyDJRNID5pK4AWj1l64Dbz0147hJgy5k2C0/ZiKK/9u5c5K+HRUVHmp+RMvGEjGh84oA5Q==", "dev": true }, "fs-extra": { @@ -19359,9 +19511,9 @@ } }, "spdx-license-ids": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", - "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.8.tgz", + "integrity": "sha512-NDgA96EnaLSvtbM7trJj+t1LUR3pirkDCcz9nOUlPb5DMBGsH7oES6C3hs3j7R9oHEa1EMvReS/BUAIT5Tcr0g==", "dev": true }, "sprintf-js": { @@ -20078,9 +20230,9 @@ "dev": true }, "type-fest": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", - "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true }, "type-is": { @@ -20132,9 +20284,9 @@ } }, "typescript": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", - "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", "dev": true }, "typical": { @@ -20144,9 +20296,9 @@ "dev": true }, "uglify-js": { - "version": "3.13.4", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.4.tgz", - "integrity": "sha512-kv7fCkIXyQIilD5/yQy8O+uagsYIOt5cZvs890W40/e/rvjMSzJw81o9Bg0tkURxzZBROtDQhW2LFjOGoK3RZw==", + "version": "3.13.6", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.6.tgz", + "integrity": "sha512-rRprLwl8RVaS+Qvx3Wh5hPfPBn9++G6xkGlUupya0s5aDmNjI7z3lnRLB3u7sN4OmbB0pWgzhM9BEJyiWAwtAA==", "dev": true, "optional": true }, @@ -20157,15 +20309,15 @@ "dev": true }, "unbox-primitive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.0.tgz", - "integrity": "sha512-P/51NX+JXyxK/aigg1/ZgyccdAxm5K1+n8+tvqSntjOivPt19gvm1VC49RWYetsiub8WViUchdxl/KWHHB0kzA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", "dev": true, "requires": { "function-bind": "^1.1.1", - "has-bigints": "^1.0.0", - "has-symbols": "^1.0.0", - "which-boxed-primitive": "^1.0.1" + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" } }, "unbzip2-stream": { @@ -20179,9 +20331,15 @@ } }, "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==", + "dev": true + }, + "unfetch": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", + "integrity": "sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==", "dev": true }, "universalify": { @@ -20245,9 +20403,9 @@ "dev": true }, "utf-8-validate": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz", - "integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.5.tgz", + "integrity": "sha512-+pnxRYsS/axEpkrrEpzYfNZGXp0IjC/9RIxwM5gntY4Koi8SHmUGSfxfWqxZdRxrtaoVstuOzUp/rbs3JSPELQ==", "dev": true, "requires": { "node-gyp-build": "^4.2.0" @@ -20352,6 +20510,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20389,9 +20553,9 @@ "dev": true }, "@types/node": { - "version": "12.20.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.10.tgz", - "integrity": "sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw==", + "version": "12.20.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.13.tgz", + "integrity": "sha512-1x8W5OpxPq+T85OUsHRP6BqXeosKmeXRtjoF39STcdf/UWLqUsoehstZKOi0CunhVqHG17AyZgpj20eRVooK6A==", "dev": true }, "cacheable-request": { @@ -20471,6 +20635,12 @@ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true } } }, @@ -20490,9 +20660,15 @@ }, "dependencies": { "@types/node": { - "version": "12.20.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.10.tgz", - "integrity": "sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw==", + "version": "12.20.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.13.tgz", + "integrity": "sha512-1x8W5OpxPq+T85OUsHRP6BqXeosKmeXRtjoF39STcdf/UWLqUsoehstZKOi0CunhVqHG17AyZgpj20eRVooK6A==", + "dev": true + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", "dev": true }, "web3-utils": { @@ -20524,6 +20700,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20556,6 +20738,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20595,6 +20783,14 @@ "web3-providers-http": "1.3.5", "web3-providers-ipc": "1.3.5", "web3-providers-ws": "1.3.5" + }, + "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + } } }, "web3-core-subscriptions": { @@ -20606,6 +20802,14 @@ "eventemitter3": "4.0.4", "underscore": "1.9.1", "web3-core-helpers": "1.3.5" + }, + "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + } } }, "web3-eth": { @@ -20629,6 +20833,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20675,6 +20885,12 @@ "@ethersproject/strings": "^5.0.4" } }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20712,6 +20928,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", @@ -20753,6 +20975,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20788,6 +21016,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20816,6 +21050,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20849,9 +21089,15 @@ }, "dependencies": { "@types/node": { - "version": "12.20.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.10.tgz", - "integrity": "sha512-TxCmnSSppKBBOzYzPR2BR25YlX5Oay8z2XGwFBInuA/Co0V9xJhLlW4kjbxKtgeNo3NOMbQP1A5Rc03y+XecPw==", + "version": "12.20.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.13.tgz", + "integrity": "sha512-1x8W5OpxPq+T85OUsHRP6BqXeosKmeXRtjoF39STcdf/UWLqUsoehstZKOi0CunhVqHG17AyZgpj20eRVooK6A==", + "dev": true + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", "dev": true }, "web3-utils": { @@ -20883,6 +21129,12 @@ "web3-utils": "1.3.5" }, "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + }, "web3-utils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.5.tgz", @@ -20920,6 +21172,14 @@ "oboe": "2.1.5", "underscore": "1.9.1", "web3-core-helpers": "1.3.5" + }, + "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + } } }, "web3-providers-ws": { @@ -20932,6 +21192,14 @@ "underscore": "1.9.1", "web3-core-helpers": "1.3.5", "websocket": "^1.0.32" + }, + "dependencies": { + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "dev": true + } } }, "web3-shh": { @@ -20947,9 +21215,9 @@ } }, "web3-utils": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.4.tgz", - "integrity": "sha512-/vC2v0MaZNpWooJfpRw63u0Y3ag2gNjAWiLtMSL6QQLmCqCy4SQIndMt/vRyx0uMoeGt1YTwSXEcHjUzOhLg0A==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.3.6.tgz", + "integrity": "sha512-hHatFaQpkQgjGVER17gNx8u1qMyaXFZtM0y0XLGH1bzsjMPlkMPLRcYOrZ00rOPfTEuYFOdrpGOqZXVmGrMZRg==", "dev": true, "requires": { "bn.js": "^4.11.9", @@ -20958,7 +21226,7 @@ "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", "randombytes": "^2.1.0", - "underscore": "1.9.1", + "underscore": "1.12.1", "utf8": "3.0.0" } }, @@ -21114,9 +21382,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "ws": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz", - "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw==", + "version": "7.4.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz", + "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==", "dev": true }, "xhr": { @@ -21188,9 +21456,9 @@ } }, "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, "yaeti": { diff --git a/package.json b/package.json index 699061c5..70ed56fa 100644 --- a/package.json +++ b/package.json @@ -17,42 +17,49 @@ "hardhat:mumbai": "hardhat --network mumbai", "hardhat:matic": "hardhat --network matic", "compile": "SKIP_LOAD=true hardhat compile", - "console:fork": "MAINNET_FORK=true hardhat console", - "test": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/*.spec.ts", - "test-amm": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-amm/*.spec.ts", - "test-amm-scenarios": "TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-amm/__setup.spec.ts test-suites/test-amm/scenario.spec.ts", - "test-scenarios": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/scenario.spec.ts", - "test-repay-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/repay-with-collateral.spec.ts", - "test-liquidate-with-collateral": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flash-liquidation-with-collateral.spec.ts", - "test-liquidate-underlying": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/liquidation-underlying.spec.ts", - "test-configurator": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/configurator.spec.ts", - "test-transfers": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts", - "test-flash": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/flashloan.spec.ts", - "test-liquidate": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/liquidation-atoken.spec.ts", - "test-deploy": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/test-init.spec.ts", - "test-pausable": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/pausable-functions.spec.ts", - "test-permit": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-permit.spec.ts", - "test-stable-and-atokens": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/atoken-transfer.spec.ts test-suites/test-aave/stable-token.spec.ts", - "test-subgraph:scenarios": "hardhat --network hardhatevm_docker test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/subgraph-scenarios.spec.ts", - "test-weth:main": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/weth-gateway.spec.ts", - "test-weth:amm": "hardhat test test-suites/test-amm/__setup.spec.ts test-suites/test-amm/weth-gateway.spec.ts", - "test-uniswap": "hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/uniswapAdapters*.spec.ts", - "test:main:check-list": "MAINNET_FORK=true TS_NODE_TRANSPILE_ONLY=1 hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/mainnet/check-list.spec.ts", + "console:fork": "FORK=main hardhat console", + "test": "npm run compile && TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-aave/*.spec.ts", + "test-amm": "npm run compile && TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-amm/*.spec.ts", + "test-amm-scenarios": "npm run compile && TS_NODE_TRANSPILE_ONLY=1 hardhat test ./test-suites/test-amm/__setup.spec.ts test-suites/test-amm/scenario.spec.ts", + "test-scenarios": "npm run compile && npx hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/scenario.spec.ts", + "test-subgraph:scenarios": "npm run compile && hardhat --network hardhatevm_docker test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/subgraph-scenarios.spec.ts", + "test:main:check-list": "npm run compile && FORK=main TS_NODE_TRANSPILE_ONLY=1 hardhat test test-suites/test-aave/__setup.spec.ts test-suites/test-aave/mainnet/check-list.spec.ts", + "test:aave": "hardhat test test-suites/test-aave/__setup.spec.ts", + "test:amm": "hardhat test test-suites/test-amm/__setup.spec.ts", "dev:coverage": "buidler compile --force && buidler coverage --network coverage", "aave:evm:dev:migration": "npm run compile && hardhat aave:dev", - "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet", - "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --verify", - "matic:mumbai:full:migration": "npm run compile && npm run hardhat:mumbai matic:mainnet", - "matic:matic:full:migration": "npm run compile && npm run hardhat:matic matic:mainnet", - "amm:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- amm:mainnet --verify", + "aave:docker:full:migration": "npm run compile && npm run hardhat:docker -- aave:mainnet --skip-registry", + "aave:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- aave:mainnet --skip-registry", + "matic:mumbai:full:migration": "npm run compile && npm run hardhat:mumbai sidechain:mainnet -- --pool Matic --skip-registry", + "matic:matic:full:migration": "npm run compile && npm run hardhat:matic sidechain:mainnet -- --pool Matic --skip-registry", + "amm:kovan:full:migration": "npm run compile && npm run hardhat:kovan -- amm:mainnet --skip-registry", + "aave:docker:full:migration:add-registry": "npm run compile && npm run hardhat:docker -- aave:mainnet", + "aave:kovan:full:migration:add-registry": "npm run compile && npm run hardhat:kovan -- aave:mainnet", + "matic:mumbai:full:migration:add-registry": "npm run compile && npm run hardhat:mumbai sidechain:mainnet -- --pool Matic", + "matic:matic:full:migration:add-registry": "npm run compile && npm run hardhat:matic sidechain:mainnet -- --pool Matic", + "amm:kovan:full:migration:add-registry": "npm run compile && npm run hardhat:kovan -- amm:mainnet", + "aave:docker:add-market-to-registry-from-config": "npm run compile && npm run hardhat:docker -- add-market-to-registry --pool Aave", + "aave:kovan:add-market-to-registry-from-config": "npm run compile && npm run hardhat:kovan -- add-market-to-registry --pool Aave", + "matic:mumbai:add-market-to-registry-from-config": "npm run compile && npm run hardhat:mumbai add-market-to-registry --pool Matic", + "amm:kovan:add-market-to-registry-from-config": "npm run compile && npm run hardhat:kovan -- add-market-to-registry --pool Amm", + "matic:matic:add-market-to-registry-from-config": "npm run compile && npm run hardhat:matic add-market-to-registry --pool Matic", + "aave:main:add-market-to-registry-from-config": "npm run compile && npm run hardhat:main -- add-market-to-registry --pool Aave", + "aave:docker:add-market-to-new-registry": "npm run compile && npm run hardhat:docker -- add-market-to-registry --pool Aave --deploy-registry", + "aave:kovan:add-market-to-new-registry": "npm run compile && npm run hardhat:kovan -- add-market-to-registry --pool Aave --verify --deploy-registry", + "matic:mumbai:add-market-to-new-registry": "npm run compile && npm run hardhat:mumbai add-market-to-registry --pool Matic --verify --deploy-registry", + "amm:kovan:add-market-to-new-registry": "npm run compile && npm run hardhat:kovan -- add-market-to-registry --pool Amm --verify --deploy-registry", + "matic:matic:add-market-to-new-registry": "npm run compile && npm run hardhat:matic -- add-market-to-registry --pool Matic --verify --deploy-registry", + "aave:main:add-market-to-new-registry": "npm run compile && npm run hardhat:matic -- add-market-to-registry --pool Matic --verify --deploy-registry", "aave:kovan:full:initialize": "npm run hardhat:kovan -- full:initialize-lending-pool --verify --pool Aave", "aave:ropsten:full:migration": "npm run compile && npm run hardhat:ropsten -- aave:mainnet --verify", "aave:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- aave:mainnet", - "aave:fork:main": "npm run compile && MAINNET_FORK=true hardhat aave:mainnet", - "amm:fork:main": "npm run compile && MAINNET_FORK=true hardhat amm:mainnet", + "aave:fork:main": "npm run compile && FORK=main hardhat aave:mainnet", + "aave:fork:kovan": "npm run compile && FORK=kovan hardhat aave:mainnet", + "amm:fork:main": "npm run compile && FORK=main hardhat amm:mainnet", + "amm:fork:kovan": "npm run compile && FORK=kovan hardhat amm:mainnet", "amm:fork:main:tenderly": "npm run compile && npm run hardhat:tenderly-main -- amm:mainnet", "aave:main:full:migration": "npm run compile && npm run hardhat:main -- aave:mainnet --verify", - "aave:main:full:initialize": "npm run compile && MAINNET_FORK=true full:initialize-tokens --pool Aave", + "aave:main:full:initialize": "npm run compile && FORK=main full:initialize-tokens --pool Aave", "amm:main:full:migration": "npm run compile && npm run hardhat:main -- amm:mainnet --verify", "prettier:check": "npx prettier -c 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", "prettier:write": "prettier --write 'tasks/**/*.ts' 'contracts/**/*.sol' 'helpers/**/*.ts' 'test-suites/test-aave/**/*.ts'", @@ -72,14 +79,15 @@ "kovan:verify": "npm run hardhat:kovan verify:general -- --all --pool Aave", "ropsten:verify": "npm run hardhat:ropsten verify:general -- --all --pool Aave", "mainnet:verify": "npm run hardhat:main verify:general -- --all --pool Aave", + "matic:mumbai:verify": "npm run hardhat:mumbai verify:general -- --all --pool Matic", + "matic:mainnet:verify": "npm run hardhat:matic verify:general -- --all --pool Matic", + "matic:mumbai:verify:tokens": "npm run hardhat:mumbai verify:tokens -- --pool Matic", + "matic:mainnet:verify:tokens": "npm run hardhat:matic verify:tokens -- --pool Matic", "kovan:verify:tokens": "npm run hardhat:kovan verify:tokens -- --pool Aave", "ropsten:verify:tokens": "npm run hardhat:ropsten verify:tokens -- --pool Aave", "mainnet:verify:tokens": "npm run hardhat:main verify:tokens -- --pool Aave", - "print-config:fork:mainnet": "MAINNET_FORK=true hardhat print-config:fork", + "print-config:fork:mainnet": "FORK=main hardhat print-config:fork", "print-config:kovan": "hardhat --network kovan print-config --pool Aave --data-provider 0xA1901785c29cBd48bfA74e46b67C736b26054fa4", - "main:fork:initialize-tokens": "npm run compile && MAINNET_FORK=true hardhat full:initialize-tokens --pool Aave", - "main:initialize-tokens": "npm run compile && hardhat --network main full:initialize-tokens --pool Aave", - "kovan:initialize-tokens": "npm run compile && hardhat --network kovan full:initialize-tokens --pool Aave", "external:deploy-assets-kovan": "npm run compile && hardhat --network kovan external:deploy-new-asset --symbol ${SYMBOL} --verify", "external:deploy-assets-main": "npm run compile && hardhat --network main external:deploy-new-asset --symbol ${SYMBOL} --verify", "prepublishOnly": "npm run compile" @@ -92,7 +100,7 @@ "@nomiclabs/hardhat-ethers": "^2.0.0", "@nomiclabs/hardhat-waffle": "^2.0.0", "@openzeppelin/contracts": "3.1.0", - "@tenderly/hardhat-tenderly": "^1.1.0-beta.4", + "@tenderly/hardhat-tenderly": "1.1.0-beta.5", "@typechain/ethers-v4": "1.0.0", "@typechain/ethers-v5": "^2.0.0", "@typechain/truffle-v4": "2.0.2", @@ -107,6 +115,7 @@ "chai": "4.2.0", "chai-bignumber": "3.0.0", "chai-bn": "^0.2.1", + "defender-relay-client": "^1.7.0", "dotenv": "^8.2.0", "eth-sig-util": "2.5.3", "ethereum-waffle": "3.0.2", @@ -143,10 +152,12 @@ "Andrey Kozlov ", "David Racero ", "Pol Sendra ", - "David Truong " + "David Truong ", + "Hadrien Charlanes " ], "license": "AGPLv3", "dependencies": { + "axios-curlirize": "^1.3.7", "tmp-promise": "^3.0.2" }, "keywords": [ diff --git a/tasks/deployments/add-market-to-registry.ts b/tasks/deployments/add-market-to-registry.ts new file mode 100644 index 00000000..0e1d4b68 --- /dev/null +++ b/tasks/deployments/add-market-to-registry.ts @@ -0,0 +1,96 @@ +import { task } from 'hardhat/config'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { waitForTx } from '../../helpers/misc-utils'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; +import { eNetwork } from '../../helpers/types'; +import { + getFirstSigner, + getLendingPoolAddressesProvider, + getLendingPoolAddressesProviderRegistry, +} from '../../helpers/contracts-getters'; +import { isAddress, parseEther } from 'ethers/lib/utils'; +import { isZeroAddress } from 'ethereumjs-util'; +import { Signer } from 'ethers'; +import { exit } from 'process'; + +task('add-market-to-registry', 'Adds address provider to registry') + .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .addOptionalParam('addressesProvider', `Address of LendingPoolAddressProvider`) + .addFlag('verify', 'Verify contracts at Etherscan') + .addFlag('deployRegistry', 'Deploy a new address provider registry') + .setAction(async ({ verify, addressesProvider, pool, deployRegistry }, DRE) => { + await DRE.run('set-DRE'); + let signer: Signer; + const network = DRE.network.name; + const poolConfig = loadPoolConfig(pool); + const { ProviderId } = poolConfig; + + let providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network); + let providerRegistryOwner = getParamPerNetwork(poolConfig.ProviderRegistryOwner, network); + const currentSignerAddress = await ( + await (await getFirstSigner()).getAddress() + ).toLocaleLowerCase(); + let deployed = false; + + if ( + deployRegistry || + !providerRegistryAddress || + !isAddress(providerRegistryAddress) || + isZeroAddress(providerRegistryAddress) + ) { + console.log('- Deploying a new Address Providers Registry:'); + + await DRE.run('full:deploy-address-provider-registry', { verify }); + + providerRegistryAddress = (await getLendingPoolAddressesProviderRegistry()).address; + providerRegistryOwner = await (await getFirstSigner()).getAddress(); + deployed = true; + } + + if ( + !providerRegistryOwner || + !isAddress(providerRegistryOwner) || + isZeroAddress(providerRegistryOwner) + ) { + throw Error('config.ProviderRegistryOwner is missing or is not an address.'); + } + + // Checks if deployer address is registry owner + if (process.env.FORK) { + await DRE.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [providerRegistryOwner], + }); + signer = DRE.ethers.provider.getSigner(providerRegistryOwner); + const firstAccount = await getFirstSigner(); + await firstAccount.sendTransaction({ value: parseEther('10'), to: providerRegistryOwner }); + } else if ( + !deployed && + providerRegistryOwner.toLocaleLowerCase() !== currentSignerAddress.toLocaleLowerCase() + ) { + console.error('ProviderRegistryOwner config does not match current signer:'); + console.error('Expected:', providerRegistryOwner); + console.error('Current:', currentSignerAddress); + exit(2); + } else { + signer = DRE.ethers.provider.getSigner(providerRegistryOwner); + } + + // 1. Address Provider Registry instance + const addressesProviderRegistry = ( + await getLendingPoolAddressesProviderRegistry(providerRegistryAddress) + ).connect(signer); + + const addressesProviderInstance = await getLendingPoolAddressesProvider(addressesProvider); + + // 2. Set the provider at the Registry + await waitForTx( + await addressesProviderRegistry.registerAddressesProvider( + addressesProviderInstance.address, + ProviderId + ) + ); + console.log( + `Added LendingPoolAddressesProvider with address "${addressesProviderInstance.address}" to registry located at ${addressesProviderRegistry.address}` + ); + }); diff --git a/tasks/deployments/deploy-UiPoolDataProvider.ts b/tasks/deployments/deploy-UiPoolDataProvider.ts index 6cc07449..7696ddb9 100644 --- a/tasks/deployments/deploy-UiPoolDataProvider.ts +++ b/tasks/deployments/deploy-UiPoolDataProvider.ts @@ -1,6 +1,7 @@ import { task } from 'hardhat/config'; -import { eContractid, eEthereumNetwork, ePolygonNetwork } from '../../helpers/types'; +import { eContractid, eEthereumNetwork, eNetwork, ePolygonNetwork } from '../../helpers/types'; import { deployUiPoolDataProvider } from '../../helpers/contracts-deployments'; +import { exit } from 'process'; task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider contract`) .addFlag('verify', 'Verify UiPoolDataProvider contract via Etherscan API.') @@ -9,8 +10,11 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider if (!localBRE.network.config.chainId) { throw new Error('INVALID_CHAIN_ID'); } + const network = localBRE.network.name; - const addressesByNetwork = { + const addressesByNetwork: { + [key: string]: { incentivesController: string; aaveOracle: string }; + } = { [eEthereumNetwork.kovan]: { incentivesController: '0x0000000000000000000000000000000000000000', aaveOracle: '0x8fb777d67e9945e2c01936e319057f9d41d559e6', @@ -28,17 +32,25 @@ task(`deploy-${eContractid.UiPoolDataProvider}`, `Deploys the UiPoolDataProvider aaveOracle: '0xC365C653f7229894F93994CD0b30947Ab69Ff1D5', }, }; + const supportedNetworks = Object.keys(addressesByNetwork); + + if (!supportedNetworks.includes(network)) { + console.error( + `[task][error] Network "${network}" not supported, please use one of: ${supportedNetworks.join()}` + ); + exit(2); + } + + const oracle = addressesByNetwork[network].aaveOracle; + const incentivesController = addressesByNetwork[network].aaveOracle; console.log(`\n- UiPoolDataProvider deployment`); - console.log(`\tDeploying UiPoolDataProvider implementation ...`); - const UiPoolDataProvider = await deployUiPoolDataProvider( - [ - addressesByNetwork[localBRE.network.name].incentivesController, - addressesByNetwork[localBRE.network.name].aaveOracle, - ], + const uiPoolDataProvider = await deployUiPoolDataProvider( + [incentivesController, oracle], verify ); - console.log(`\tFinished UiPoolDataProvider deployment: ${UiPoolDataProvider.address}`); + console.log('UiPoolDataProvider deployed at:', uiPoolDataProvider.address); + console.log(`\tFinished UiPoolDataProvider deployment`); }); diff --git a/tasks/deployments/deploy-UniswapLiquiditySwapAdapter.ts b/tasks/deployments/deploy-UniswapLiquiditySwapAdapter.ts index a41cd975..70eb6ced 100644 --- a/tasks/deployments/deploy-UniswapLiquiditySwapAdapter.ts +++ b/tasks/deployments/deploy-UniswapLiquiditySwapAdapter.ts @@ -1,8 +1,9 @@ import { task } from 'hardhat/config'; import { UniswapLiquiditySwapAdapterFactory } from '../../types'; -import { verifyContract } from '../../helpers/etherscan-verification'; +import { verifyContract } from '../../helpers/contracts-helpers'; import { getFirstSigner } from '../../helpers/contracts-getters'; +import { eContractid } from '../../helpers/types'; const CONTRACT_NAME = 'UniswapLiquiditySwapAdapter'; @@ -29,7 +30,14 @@ task(`deploy-${CONTRACT_NAME}`, `Deploys the ${CONTRACT_NAME} contract`) ).deploy(provider, router, weth); await uniswapRepayAdapter.deployTransaction.wait(); console.log(`${CONTRACT_NAME}.address`, uniswapRepayAdapter.address); - await verifyContract(uniswapRepayAdapter.address, [provider, router, weth]); + + if (verify) { + await verifyContract(eContractid.UniswapLiquiditySwapAdapter, uniswapRepayAdapter, [ + provider, + router, + weth, + ]); + } console.log(`\tFinished ${CONTRACT_NAME} proxy and implementation deployment`); }); diff --git a/tasks/deployments/deploy-UniswapRepayAdapter.ts b/tasks/deployments/deploy-UniswapRepayAdapter.ts index 58ba23a1..e9e7b244 100644 --- a/tasks/deployments/deploy-UniswapRepayAdapter.ts +++ b/tasks/deployments/deploy-UniswapRepayAdapter.ts @@ -1,8 +1,9 @@ import { task } from 'hardhat/config'; import { UniswapRepayAdapterFactory } from '../../types'; -import { verifyContract } from '../../helpers/etherscan-verification'; +import { verifyContract } from '../../helpers/contracts-helpers'; import { getFirstSigner } from '../../helpers/contracts-getters'; +import { eContractid } from '../../helpers/types'; const CONTRACT_NAME = 'UniswapRepayAdapter'; @@ -30,7 +31,14 @@ task(`deploy-${CONTRACT_NAME}`, `Deploys the ${CONTRACT_NAME} contract`) ); await uniswapRepayAdapter.deployTransaction.wait(); console.log(`${CONTRACT_NAME}.address`, uniswapRepayAdapter.address); - await verifyContract(uniswapRepayAdapter.address, [provider, router, weth]); + + if (verify) { + await verifyContract(eContractid.UniswapRepayAdapter, uniswapRepayAdapter, [ + provider, + router, + weth, + ]); + } console.log( `\tFinished ${CONTRACT_NAME}${CONTRACT_NAME}lDataProvider proxy and implementation deployment` diff --git a/tasks/dev/2_address_provider_registry.ts b/tasks/dev/2_address_provider_registry.ts index 42f42a7b..bfa201d4 100644 --- a/tasks/dev/2_address_provider_registry.ts +++ b/tasks/dev/2_address_provider_registry.ts @@ -3,6 +3,7 @@ import { deployLendingPoolAddressesProvider, deployLendingPoolAddressesProviderRegistry, } from '../../helpers/contracts-deployments'; +import { getEthersSigners } from '../../helpers/contracts-helpers'; import { waitForTx } from '../../helpers/misc-utils'; import { AaveConfig } from '../../markets/aave'; @@ -14,10 +15,11 @@ task( .setAction(async ({ verify }, localBRE) => { await localBRE.run('set-DRE'); - const admin = await (await localBRE.ethers.getSigners())[0].getAddress(); + const admin = await (await getEthersSigners())[0].getAddress(); const addressesProvider = await deployLendingPoolAddressesProvider(AaveConfig.MarketId, verify); await waitForTx(await addressesProvider.setPoolAdmin(admin)); + await waitForTx(await addressesProvider.setEmergencyAdmin(admin)); const addressesProviderRegistry = await deployLendingPoolAddressesProviderRegistry(verify); await waitForTx( diff --git a/tasks/dev/5_initialize.ts b/tasks/dev/5_initialize.ts index a1ad9970..f36a4e09 100644 --- a/tasks/dev/5_initialize.ts +++ b/tasks/dev/5_initialize.ts @@ -4,7 +4,6 @@ import { deployMockFlashLoanReceiver, deployWalletBalancerProvider, deployAaveProtocolDataProvider, - deployWETHGateway, authorizeWETHGateway, } from '../../helpers/contracts-deployments'; import { getParamPerNetwork } from '../../helpers/contracts-helpers'; @@ -13,18 +12,18 @@ import { ConfigNames, getReservesConfigByPool, getTreasuryAddress, - getWethAddress, loadPoolConfig, } from '../../helpers/configuration'; import { tEthereumAddress, AavePools, eContractid } from '../../helpers/types'; -import { waitForTx, filterMapBy } from '../../helpers/misc-utils'; +import { waitForTx, filterMapBy, notFalsyOrZeroAddress } from '../../helpers/misc-utils'; import { configureReservesByHelper, initReservesByHelper } from '../../helpers/init-helpers'; import { getAllTokenAddresses } from '../../helpers/mock-helpers'; import { ZERO_ADDRESS } from '../../helpers/constants'; import { getAllMockedTokens, getLendingPoolAddressesProvider, + getWETHGateway, } from '../../helpers/contracts-getters'; import { insertContractAddressInDb } from '../../helpers/contracts-helpers'; @@ -92,6 +91,10 @@ task('dev:initialize-lending-pool', 'Initialize lending pool configuration.') await insertContractAddressInDb(eContractid.AaveProtocolDataProvider, testHelpers.address); const lendingPoolAddress = await addressesProvider.getLendingPool(); - const gateWay = await getParamPerNetwork(WethGateway, network); - await authorizeWETHGateway(gateWay, lendingPoolAddress); + + let gateway = getParamPerNetwork(WethGateway, network); + if (!notFalsyOrZeroAddress(gateway)) { + gateway = (await getWETHGateway()).address; + } + await authorizeWETHGateway(gateway, lendingPoolAddress); }); diff --git a/tasks/full/0_address_provider_registry.ts b/tasks/full/0_address_provider_registry.ts index 19b5e1f2..853088eb 100644 --- a/tasks/full/0_address_provider_registry.ts +++ b/tasks/full/0_address_provider_registry.ts @@ -1,11 +1,30 @@ +import { formatEther } from 'ethers/lib/utils'; import { task } from 'hardhat/config'; +import { ConfigNames, loadPoolConfig } from '../../helpers/configuration'; import { deployLendingPoolAddressesProviderRegistry } from '../../helpers/contracts-deployments'; +import { getFirstSigner } from '../../helpers/contracts-getters'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; +import { notFalsyOrZeroAddress } from '../../helpers/misc-utils'; +import { eNetwork } from '../../helpers/types'; task('full:deploy-address-provider-registry', 'Deploy address provider registry') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({ verify }, DRE) => { + .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) + .setAction(async ({ verify, pool }, DRE) => { await DRE.run('set-DRE'); + const poolConfig = loadPoolConfig(pool); + const network = DRE.network.name; + const signer = await getFirstSigner(); - const contract = await deployLendingPoolAddressesProviderRegistry(verify); - console.log('Registry Address:', contract.address); + const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network); + + console.log('Signer', await signer.getAddress()); + console.log('Balance', formatEther(await signer.getBalance())); + + if (notFalsyOrZeroAddress(providerRegistryAddress)) { + console.log('Already deployed Provider Registry Address at', providerRegistryAddress); + } else { + const contract = await deployLendingPoolAddressesProviderRegistry(verify); + console.log('Deployed Registry Address:', contract.address); + } }); diff --git a/tasks/full/1_address_provider.ts b/tasks/full/1_address_provider.ts index d9563ebc..c863ae05 100644 --- a/tasks/full/1_address_provider.ts +++ b/tasks/full/1_address_provider.ts @@ -1,9 +1,5 @@ import { task } from 'hardhat/config'; -import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { - deployLendingPoolAddressesProvider, - deployLendingPoolAddressesProviderRegistry, -} from '../../helpers/contracts-deployments'; +import { deployLendingPoolAddressesProvider } from '../../helpers/contracts-deployments'; import { notFalsyOrZeroAddress, waitForTx } from '../../helpers/misc-utils'; import { ConfigNames, @@ -11,16 +7,8 @@ import { getGenesisPoolAdmin, getEmergencyAdmin, } from '../../helpers/configuration'; +import { getParamPerNetwork } from '../../helpers/contracts-helpers'; import { eNetwork } from '../../helpers/types'; -import { - getFirstSigner, - getLendingPoolAddressesProviderRegistry, -} from '../../helpers/contracts-getters'; -import { formatEther, isAddress, parseEther } from 'ethers/lib/utils'; -import { isZeroAddress } from 'ethereumjs-util'; -import { Signer, BigNumber } from 'ethers'; -import { parse } from 'path'; -//import BigNumber from 'bignumber.js'; task( 'full:deploy-address-provider', @@ -28,65 +16,29 @@ task( ) .addFlag('verify', 'Verify contracts at Etherscan') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) - .setAction(async ({ verify, pool }, DRE) => { + .addFlag('skipRegistry') + .setAction(async ({ verify, pool, skipRegistry }, DRE) => { await DRE.run('set-DRE'); - let signer: Signer; - const network = DRE.network.name; const poolConfig = loadPoolConfig(pool); - const { ProviderId, MarketId } = poolConfig; + const { MarketId } = poolConfig; - const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network); - const providerRegistryOwner = getParamPerNetwork(poolConfig.ProviderRegistryOwner, network); - - if ( - !providerRegistryAddress || - !isAddress(providerRegistryAddress) || - isZeroAddress(providerRegistryAddress) - ) { - throw Error('config.ProviderRegistry is missing or is not an address.'); - } - - if ( - !providerRegistryOwner || - !isAddress(providerRegistryOwner) || - isZeroAddress(providerRegistryOwner) - ) { - throw Error('config.ProviderRegistryOwner is missing or is not an address.'); - } - - // Checks if deployer address is registry owner - if (process.env.MAINNET_FORK === 'true') { - await DRE.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [providerRegistryOwner], - }); - signer = DRE.ethers.provider.getSigner(providerRegistryOwner); - const firstAccount = await getFirstSigner(); - await firstAccount.sendTransaction({ value: parseEther('10'), to: providerRegistryOwner }); - } else { - signer = DRE.ethers.provider.getSigner(providerRegistryOwner); - } - // 1. Address Provider Registry instance - const addressesProviderRegistry = ( - await getLendingPoolAddressesProviderRegistry(providerRegistryAddress) - ).connect(signer); - - console.log('Registry Address', addressesProviderRegistry.address); - - // 2. Deploy address provider and set genesis manager + // 1. Deploy address provider and set genesis manager const addressesProvider = await deployLendingPoolAddressesProvider(MarketId, verify); - // DISABLE SEC. 3 FOR GOVERNANCE USE! - // 3. Set the provider at the Registry - await waitForTx( - await addressesProviderRegistry.registerAddressesProvider( - addressesProvider.address, - ProviderId - ) - ); - - // 4. Set pool admins + // 2. Add to registry or setup a new one + if (!skipRegistry) { + const providerRegistryAddress = getParamPerNetwork( + poolConfig.ProviderRegistry, + DRE.network.name + ); + await DRE.run('add-market-to-registry', { + pool, + addressesProvider: addressesProvider.address, + deployRegistry: !notFalsyOrZeroAddress(providerRegistryAddress), + }); + } + // 3. Set pool admins await waitForTx(await addressesProvider.setPoolAdmin(await getGenesisPoolAdmin(poolConfig))); await waitForTx(await addressesProvider.setEmergencyAdmin(await getEmergencyAdmin(poolConfig))); diff --git a/tasks/full/2_lending_pool.ts b/tasks/full/2_lending_pool.ts index 5f92b8eb..e318846e 100644 --- a/tasks/full/2_lending_pool.ts +++ b/tasks/full/2_lending_pool.ts @@ -34,6 +34,7 @@ task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') console.log('\tDeploying new lending pool implementation & libraries...'); const lendingPoolImpl = await deployLendingPool(verify); lendingPoolImplAddress = lendingPoolImpl.address; + await lendingPoolImpl.initialize(addressesProvider.address); } console.log('\tSetting lending pool implementation with address:', lendingPoolImplAddress); // Set lending pool impl to Address provider @@ -81,7 +82,7 @@ task('full:deploy-lending-pool', 'Deploy lending pool for dev enviroment') if (DRE.network.name.includes('tenderly')) { const transactionLink = `https://dashboard.tenderly.co/${DRE.config.tenderly.username}/${ DRE.config.tenderly.project - }/fork/${DRE.tenderlyRPC.getFork()}/simulation/${DRE.tenderlyRPC.getHead()}`; + }/fork/${DRE.tenderlyNetwork.getFork()}/simulation/${DRE.tenderlyNetwork.getHead()}`; console.error('Check tx error:', transactionLink); } throw error; diff --git a/tasks/full/3_oracles.ts b/tasks/full/3_oracles.ts index e3f8f27f..df06f34c 100644 --- a/tasks/full/3_oracles.ts +++ b/tasks/full/3_oracles.ts @@ -17,7 +17,7 @@ import { getLendingRateOracle, getPairsTokenAggregator, } from '../../helpers/contracts-getters'; -import { AaveOracle } from '../../types'; +import { AaveOracle, LendingRateOracle } from '../../types'; task('full:deploy-oracles', 'Deploy oracles for dev enviroment') .addFlag('verify', 'Verify contracts at Etherscan') @@ -49,38 +49,34 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') const [tokens, aggregators] = getPairsTokenAggregator(tokensToWatch, chainlinkAggregators); let aaveOracle: AaveOracle; + let lendingRateOracle: LendingRateOracle; + if (notFalsyOrZeroAddress(aaveOracleAddress)) { aaveOracle = await await getAaveOracle(aaveOracleAddress); - const owner = await aaveOracle.owner(); - const signer = DRE.ethers.provider.getSigner(owner); - - aaveOracle = await (await getAaveOracle(aaveOracleAddress)).connect(signer); - await waitForTx(await aaveOracle.setAssetSources(tokens, aggregators)); } else { aaveOracle = await deployAaveOracle( [tokens, aggregators, fallbackOracleAddress, await getWethAddress(poolConfig)], verify ); + await waitForTx(await aaveOracle.setAssetSources(tokens, aggregators)); } - let lendingRateOracle = notFalsyOrZeroAddress(lendingRateOracleAddress) - ? await getLendingRateOracle(lendingRateOracleAddress) - : await deployLendingRateOracle(verify); - const { USD, ...tokensAddressesWithoutUsd } = tokensToWatch; + if (notFalsyOrZeroAddress(lendingRateOracleAddress)) { + lendingRateOracle = await getLendingRateOracle(lendingRateOracleAddress); + } else { + lendingRateOracle = await deployLendingRateOracle(verify); + const { USD, ...tokensAddressesWithoutUsd } = tokensToWatch; + await setInitialMarketRatesInRatesOracleByHelper( + lendingRateOracles, + tokensAddressesWithoutUsd, + lendingRateOracle, + admin + ); + } + + console.log('Aave Oracle: %s', lendingRateOracle.address); + console.log('Lending Rate Oracle: %s', lendingRateOracle.address); - lendingRateOracle = lendingRateOracle.connect( - DRE.ethers.provider.getSigner(await lendingRateOracle.owner()) - ); - // This must be done any time a new market is created I believe - //if (!lendingRateOracleAddress) { - await setInitialMarketRatesInRatesOracleByHelper( - lendingRateOracles, - tokensAddressesWithoutUsd, - lendingRateOracle, - admin - ); - //} - console.log('ORACLES: %s and %s', aaveOracle.address, lendingRateOracle.address); // Register the proxy price provider on the addressesProvider await waitForTx(await addressesProvider.setPriceOracle(aaveOracle.address)); await waitForTx(await addressesProvider.setLendingRateOracle(lendingRateOracle.address)); @@ -88,7 +84,7 @@ task('full:deploy-oracles', 'Deploy oracles for dev enviroment') if (DRE.network.name.includes('tenderly')) { const transactionLink = `https://dashboard.tenderly.co/${DRE.config.tenderly.username}/${ DRE.config.tenderly.project - }/fork/${DRE.tenderlyRPC.getFork()}/simulation/${DRE.tenderlyRPC.getHead()}`; + }/fork/${DRE.tenderlyNetwork.getFork()}/simulation/${DRE.tenderlyNetwork.getHead()}`; console.error('Check tx error:', transactionLink); } throw error; diff --git a/tasks/full/5-deploy-wethGateWay.ts b/tasks/full/5-deploy-wethGateWay.ts index 2774f107..6240693a 100644 --- a/tasks/full/5-deploy-wethGateWay.ts +++ b/tasks/full/5-deploy-wethGateWay.ts @@ -1,10 +1,10 @@ import { task } from 'hardhat/config'; -import { AaveConfig } from '../../markets/aave/index'; -import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { loadPoolConfig, ConfigNames, getWethAddress } from '../../helpers/configuration'; +import { + loadPoolConfig, + ConfigNames, + getWrappedNativeTokenAddress, +} from '../../helpers/configuration'; import { deployWETHGateway } from '../../helpers/contracts-deployments'; -import { DRE } from '../../helpers/misc-utils'; -import { eNetwork } from '../../helpers/types'; const CONTRACT_NAME = 'WETHGateway'; @@ -13,20 +13,13 @@ task(`full-deploy-weth-gateway`, `Deploys the ${CONTRACT_NAME} contract`) .addFlag('verify', `Verify ${CONTRACT_NAME} contract via Etherscan API.`) .setAction(async ({ verify, pool }, localBRE) => { await localBRE.run('set-DRE'); - const network = localBRE.network.name; const poolConfig = loadPoolConfig(pool); - const Weth = await getWethAddress(poolConfig); - const { WethGateway } = poolConfig; + const Weth = await getWrappedNativeTokenAddress(poolConfig); if (!localBRE.network.config.chainId) { throw new Error('INVALID_CHAIN_ID'); } - let gateWay = getParamPerNetwork(WethGateway, network); - if (gateWay === '') { - const wethGateWay = await deployWETHGateway([Weth], verify); - console.log(`${CONTRACT_NAME}.address`, wethGateWay.address); - console.log(`\tFinished ${CONTRACT_NAME} deployment`); - } else { - console.log(`Weth gateway already deployed. Address: ${gateWay}`); - } + const wethGateWay = await deployWETHGateway([Weth], verify); + console.log(`${CONTRACT_NAME}.address`, wethGateWay.address); + console.log(`\tFinished ${CONTRACT_NAME} deployment`); }); diff --git a/tasks/full/6-initialize.ts b/tasks/full/6-initialize.ts index f4384e09..bfe2925e 100644 --- a/tasks/full/6-initialize.ts +++ b/tasks/full/6-initialize.ts @@ -40,10 +40,11 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') ReservesConfig, LendingPoolCollateralManager, WethGateway, + IncentivesController, } = poolConfig as ICommonConfiguration; const reserveAssets = await getParamPerNetwork(ReserveAssets, network); - + const incentivesController = await getParamPerNetwork(IncentivesController, network); const addressesProvider = await getLendingPoolAddressesProvider(); const testHelpers = await getAaveProtocolDataProvider(); @@ -64,7 +65,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') SymbolPrefix, admin, treasuryAddress, - ZERO_ADDRESS, + incentivesController, verify ); await configureReservesByHelper(ReservesConfig, reserveAssets, testHelpers, admin); @@ -87,6 +88,18 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') await addressesProvider.setLendingPoolCollateralManager(collateralManagerAddress) ); + console.log( + '\tSetting AaveProtocolDataProvider at AddressesProvider at id: 0x01', + collateralManagerAddress + ); + const aaveProtocolDataProvider = await getAaveProtocolDataProvider(); + await waitForTx( + await addressesProvider.setAddress( + '0x0100000000000000000000000000000000000000000000000000000000000000', + aaveProtocolDataProvider.address + ) + ); + await deployWalletBalancerProvider(verify); const lendingPoolAddress = await addressesProvider.getLendingPool(); @@ -95,6 +108,7 @@ task('full:initialize-lending-pool', 'Initialize lending pool configuration.') if (!notFalsyOrZeroAddress(gateWay)) { gateWay = (await getWETHGateway()).address; } + console.log('GATEWAY', gateWay); await authorizeWETHGateway(gateWay, lendingPoolAddress); } catch (err) { console.error(err); diff --git a/tasks/migrations/aave.dev.ts b/tasks/migrations/aave.dev.ts index 16ff3a6a..86608c75 100644 --- a/tasks/migrations/aave.dev.ts +++ b/tasks/migrations/aave.dev.ts @@ -29,7 +29,10 @@ task('aave:dev', 'Deploy development enviroment') console.log('4. Deploy oracles'); await localBRE.run('dev:deploy-oracles', { verify, pool: POOL_NAME }); - console.log('5. Initialize lending pool'); + console.log('5. Deploy WETH Gateway'); + await localBRE.run('full-deploy-weth-gateway', { verify, pool: POOL_NAME }); + + console.log('6. Initialize lending pool'); await localBRE.run('dev:initialize-lending-pool', { verify, pool: POOL_NAME }); console.log('\nFinished migration'); diff --git a/tasks/migrations/aave.mainnet.ts b/tasks/migrations/aave.mainnet.ts index 184f6e47..231f0659 100644 --- a/tasks/migrations/aave.mainnet.ts +++ b/tasks/migrations/aave.mainnet.ts @@ -6,7 +6,8 @@ import { usingTenderly } from '../../helpers/tenderly-utils'; task('aave:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({ verify }, DRE) => { + .addFlag('skipRegistry', 'Skip addresses provider registration at Addresses Provider Registry') + .setAction(async ({ verify, skipRegistry }, DRE) => { const POOL_NAME = ConfigNames.Aave; await DRE.run('set-DRE'); @@ -18,7 +19,7 @@ task('aave:mainnet', 'Deploy development enviroment') console.log('Migration started\n'); console.log('1. Deploy address provider'); - await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); + await DRE.run('full:deploy-address-provider', { pool: POOL_NAME, skipRegistry }); console.log('2. Deploy lending pool'); await DRE.run('full:deploy-lending-pool', { pool: POOL_NAME }); @@ -45,8 +46,8 @@ task('aave:mainnet', 'Deploy development enviroment') } if (usingTenderly()) { - const postDeployHead = DRE.tenderlyRPC.getHead(); - const postDeployFork = DRE.tenderlyRPC.getFork(); + const postDeployHead = DRE.tenderlyNetwork.getHead(); + const postDeployFork = DRE.tenderlyNetwork.getFork(); console.log('Tenderly Info'); console.log('- Head', postDeployHead); console.log('- Fork', postDeployFork); diff --git a/tasks/migrations/amm.mainnet.ts b/tasks/migrations/amm.mainnet.ts index e496fc82..b6fc8d11 100644 --- a/tasks/migrations/amm.mainnet.ts +++ b/tasks/migrations/amm.mainnet.ts @@ -6,7 +6,8 @@ import { usingTenderly } from '../../helpers/tenderly-utils'; task('amm:mainnet', 'Deploy development enviroment') .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({ verify }, DRE) => { + .addFlag('skipRegistry', 'Skip addresses provider registration at Addresses Provider Registry') + .setAction(async ({ verify, skipRegistry }, DRE) => { const POOL_NAME = ConfigNames.Amm; await DRE.run('set-DRE'); @@ -18,7 +19,7 @@ task('amm:mainnet', 'Deploy development enviroment') console.log('Migration started\n'); console.log('1. Deploy address provider'); - await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); + await DRE.run('full:deploy-address-provider', { pool: POOL_NAME, skipRegistry }); console.log('2. Deploy lending pool'); await DRE.run('full:deploy-lending-pool', { pool: POOL_NAME }); @@ -45,8 +46,8 @@ task('amm:mainnet', 'Deploy development enviroment') } if (usingTenderly()) { - const postDeployHead = DRE.tenderlyRPC.getHead(); - const postDeployFork = DRE.tenderlyRPC.getFork(); + const postDeployHead = DRE.tenderlyNetwork.getHead(); + const postDeployFork = DRE.tenderlyNetwork.getFork(); console.log('Tenderly Info'); console.log('- Head', postDeployHead); console.log('- Fork', postDeployFork); diff --git a/tasks/migrations/matic.mainnet.ts b/tasks/migrations/sidechain.mainnet.ts similarity index 62% rename from tasks/migrations/matic.mainnet.ts rename to tasks/migrations/sidechain.mainnet.ts index 5c2f7f09..e563d8f2 100644 --- a/tasks/migrations/matic.mainnet.ts +++ b/tasks/migrations/sidechain.mainnet.ts @@ -4,10 +4,12 @@ import { ConfigNames } from '../../helpers/configuration'; import { printContracts } from '../../helpers/misc-utils'; import { usingTenderly } from '../../helpers/tenderly-utils'; -task('matic:mainnet', 'Deploy development enviroment') +task('sidechain:mainnet', 'Deploy market at sidechain') + .addParam('pool', `Market pool configuration, one of ${Object.keys(ConfigNames)}`) .addFlag('verify', 'Verify contracts at Etherscan') - .setAction(async ({ verify }, DRE) => { - const POOL_NAME = ConfigNames.Matic; + .addFlag('skipRegistry', 'Skip addresses provider registration at Addresses Provider Registry') + .setAction(async ({ verify, pool, skipRegistry }, DRE) => { + const POOL_NAME = pool; await DRE.run('set-DRE'); // Prevent loss of gas verifying all the needed ENVs for Etherscan verification @@ -17,8 +19,11 @@ task('matic:mainnet', 'Deploy development enviroment') console.log('Migration started\n'); + console.log('0. Deploy address provider registry'); + await DRE.run('full:deploy-address-provider-registry', { pool: POOL_NAME }); + console.log('1. Deploy address provider'); - await DRE.run('full:deploy-address-provider', { pool: POOL_NAME }); + await DRE.run('full:deploy-address-provider', { pool: POOL_NAME, skipRegistry }); console.log('2. Deploy lending pool'); await DRE.run('full:deploy-lending-pool', { pool: POOL_NAME }); @@ -28,22 +33,24 @@ task('matic:mainnet', 'Deploy development enviroment') console.log('4. Deploy Data Provider'); await DRE.run('full:data-provider', { pool: POOL_NAME }); + console.log('5. Deploy WETH Gateway'); + await DRE.run('full-deploy-weth-gateway', { pool: POOL_NAME }); - console.log('5. Initialize lending pool'); + console.log('6. Initialize lending pool'); await DRE.run('full:initialize-lending-pool', { pool: POOL_NAME }); if (verify) { printContracts(); - console.log('4. Veryfing contracts'); + console.log('7. Veryfing contracts'); await DRE.run('verify:general', { all: true, pool: POOL_NAME }); - console.log('5. Veryfing aTokens and debtTokens'); + console.log('8. Veryfing aTokens and debtTokens'); await DRE.run('verify:tokens', { pool: POOL_NAME }); } if (usingTenderly()) { - const postDeployHead = DRE.tenderlyRPC.getHead(); - const postDeployFork = DRE.tenderlyRPC.getFork(); + const postDeployHead = DRE.tenderlyNetwork.getHead(); + const postDeployFork = DRE.tenderlyNetwork.getFork(); console.log('Tenderly Info'); console.log('- Head', postDeployHead); console.log('- Fork', postDeployFork); diff --git a/tasks/misc/initialize-tokens.ts b/tasks/misc/initialize-tokens.ts deleted file mode 100644 index 342e6e1a..00000000 --- a/tasks/misc/initialize-tokens.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { task } from 'hardhat/config'; -import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { loadPoolConfig, ConfigNames, getTreasuryAddress } from '../../helpers/configuration'; -import { eEthereumNetwork, eNetwork, ICommonConfiguration } from '../../helpers/types'; -import { waitForTx } from '../../helpers/misc-utils'; -import { initTokenReservesByHelper } from '../../helpers/init-helpers'; -import { exit } from 'process'; -import { - getFirstSigner, - getLendingPoolAddressesProvider, - getLendingPoolAddressesProviderRegistry, -} from '../../helpers/contracts-getters'; -import { Signer } from 'ethers'; -import { formatEther, parseEther } from 'ethers/lib/utils'; - -task('full:initialize-tokens', 'Initialize lending pool configuration.') - .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) - .addParam('ratesDeployer', `RatesHelper address `) - .addParam('dataProvider', `Data provider address`) - .addFlag('verify') - .setAction(async ({ verify, pool, dataProvider, ratesDeployer }, DRE) => { - try { - await DRE.run('set-DRE'); - let signer: Signer; - const network = - process.env.MAINNET_FORK === 'true' ? eEthereumNetwork.main : DRE.network.name; - const poolConfig = loadPoolConfig(pool); - const { ReserveAssets, ReservesConfig } = poolConfig as ICommonConfiguration; - - const reserveAssets = await getParamPerNetwork(ReserveAssets, network); - - const treasuryAddress = await getTreasuryAddress(poolConfig); - const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network); - const providerRegistryOwner = getParamPerNetwork(poolConfig.ProviderRegistryOwner, network); - - const providerRegistry = await getLendingPoolAddressesProviderRegistry( - providerRegistryAddress - ); - - const providers = await providerRegistry.getAddressesProvidersList(); - - const addressesProvider = await getLendingPoolAddressesProvider(providers[0]); // Checks first provider - - const admin = await addressesProvider.getPoolAdmin(); - if (!reserveAssets) { - throw 'Reserve assets is undefined. Check ReserveAssets configuration at config directory'; - } - - if (process.env.MAINNET_FORK === 'true') { - await DRE.network.provider.request({ - method: 'hardhat_impersonateAccount', - params: [providerRegistryOwner], - }); - signer = DRE.ethers.provider.getSigner(providerRegistryOwner); - const user = await getFirstSigner(); - await waitForTx( - await user.sendTransaction({ to: await signer.getAddress(), value: parseEther('10') }) - ); - - const balance = await signer.getBalance(); - console.log('signer balance', formatEther(balance)); - } else { - signer = DRE.ethers.provider.getSigner(providerRegistryOwner); - } - - // Init unitilialized reserves - await initTokenReservesByHelper( - ReservesConfig, - reserveAssets, - admin, - addressesProvider.address, - ratesDeployer, - dataProvider, - signer, - treasuryAddress, - verify - ); - - // Show contracts state - await DRE.run('print-config', { - pool: 'Aave', - dataProvider, - }); - } catch (err) { - console.error(err); - exit(1); - } - }); diff --git a/tasks/misc/print-config.ts b/tasks/misc/print-config.ts index 722d308c..fe3925d3 100644 --- a/tasks/misc/print-config.ts +++ b/tasks/misc/print-config.ts @@ -14,10 +14,10 @@ task('print-config', 'Inits the DRE, to have access to all the plugins') .addParam('pool', `Pool name to retrieve configuration, supported: ${Object.values(ConfigNames)}`) .setAction(async ({ pool, dataProvider }, localBRE) => { await localBRE.run('set-DRE'); - const network = - process.env.MAINNET_FORK === 'true' - ? eEthereumNetwork.main - : (localBRE.network.name as eNetwork); + const network = process.env.FORK + ? (process.env.FORK as eNetwork) + : (localBRE.network.name as eNetwork); + console.log(network); const poolConfig = loadPoolConfig(pool); const providerRegistryAddress = getParamPerNetwork(poolConfig.ProviderRegistry, network); @@ -60,7 +60,7 @@ task('print-config', 'Inits the DRE, to have access to all the plugins') ]; const tokensFields = ['aToken', 'stableDebtToken', 'variableDebtToken']; for (const [symbol, address] of Object.entries( - getParamPerNetwork(poolConfig.ReserveAssets, network) + getParamPerNetwork(poolConfig.ReserveAssets, network as eNetwork) )) { console.log(`- ${symbol} asset config`); console.log(` - reserve address: ${address}`); diff --git a/tasks/misc/set-bre.ts b/tasks/misc/set-bre.ts index 63721451..fd5a60d6 100644 --- a/tasks/misc/set-bre.ts +++ b/tasks/misc/set-bre.ts @@ -1,10 +1,6 @@ import { task } from 'hardhat/config'; import { DRE, setDRE } from '../../helpers/misc-utils'; -import { EthereumNetworkNames } from '../../helpers/types'; -import { usingTenderly } from '../../helpers/tenderly-utils'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { getFirstSigner } from '../../helpers/contracts-getters'; -import { formatEther } from 'ethers/lib/utils'; task(`set-DRE`, `Inits the DRE, to have access to all the plugins' objects`).setAction( async (_, _DRE) => { @@ -16,26 +12,36 @@ task(`set-DRE`, `Inits the DRE, to have access to all the plugins' objects`).set process.env.TENDERLY === 'true' ) { console.log('- Setting up Tenderly provider'); + const net = _DRE.tenderly.network(); + if (process.env.TENDERLY_FORK_ID && process.env.TENDERLY_HEAD_ID) { console.log('- Connecting to a Tenderly Fork'); - _DRE.tenderlyRPC.setFork(process.env.TENDERLY_FORK_ID); - _DRE.tenderlyRPC.setHead(process.env.TENDERLY_HEAD_ID); + await net.setFork(process.env.TENDERLY_FORK_ID); + await net.setHead(process.env.TENDERLY_HEAD_ID); } else { console.log('- Creating a new Tenderly Fork'); - await _DRE.tenderlyRPC.initializeFork(); + await net.initializeFork(); } - const provider = new _DRE.ethers.providers.Web3Provider(_DRE.tenderlyRPC as any); + const provider = new _DRE.ethers.providers.Web3Provider(net); _DRE.ethers.provider = provider; console.log('- Initialized Tenderly fork:'); - console.log(' - Fork: ', _DRE.tenderlyRPC.getFork()); - console.log(' - Head: ', _DRE.tenderlyRPC.getHead()); - console.log(' - First account:', await (await _DRE.ethers.getSigners())[0].getAddress()); - console.log( - ' - Balance:', - formatEther(await (await _DRE.ethers.getSigners())[0].getBalance()) - ); + console.log(' - Fork: ', net.getFork()); + console.log(' - Head: ', net.getHead()); } + console.log('- Enviroment'); + if (process.env.FORK) { + console.log(' - Fork Mode activated at network: ', process.env.FORK); + if (_DRE?.config?.networks?.hardhat?.forking?.url) { + console.log(' - Provider URL:', _DRE.config.networks.hardhat.forking?.url?.split('/')[2]); + } else { + console.error( + `[FORK][Error], missing Provider URL for "${_DRE.network.name}" network. Fill the URL at './helper-hardhat-config.ts' file` + ); + } + } + console.log(' - Network :', _DRE.network.name); + setDRE(_DRE); return _DRE; } diff --git a/tasks/misc/verify-sc.ts b/tasks/misc/verify-sc.ts index 12484d47..e65820a0 100644 --- a/tasks/misc/verify-sc.ts +++ b/tasks/misc/verify-sc.ts @@ -1,6 +1,5 @@ import { task } from 'hardhat/config'; -import { verifyContract, checkVerification } from '../../helpers/etherscan-verification'; - +import { verifyEtherscanContract, checkVerification } from '../../helpers/etherscan-verification'; interface VerifyParams { contractName: string; address: string; @@ -24,6 +23,6 @@ task('verify-sc', 'Inits the DRE, to have access to all the plugins') checkVerification(); - const result = await verifyContract(address, constructorArguments, libraries); + const result = await verifyEtherscanContract(address, constructorArguments, libraries); return result; }); diff --git a/tasks/verifications/1_general.ts b/tasks/verifications/1_general.ts index fef0e510..b2b3bcb7 100644 --- a/tasks/verifications/1_general.ts +++ b/tasks/verifications/1_general.ts @@ -19,13 +19,13 @@ import { getLendingPoolConfiguratorImpl, getLendingPoolConfiguratorProxy, getLendingPoolImpl, + getProxy, getWalletProvider, getWETHGateway, } from '../../helpers/contracts-getters'; -import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { verifyContract } from '../../helpers/etherscan-verification'; +import { verifyContract, getParamPerNetwork } from '../../helpers/contracts-helpers'; import { notFalsyOrZeroAddress } from '../../helpers/misc-utils'; -import { eNetwork, ICommonConfiguration } from '../../helpers/types'; +import { eContractid, eNetwork, ICommonConfiguration } from '../../helpers/types'; task('verify:general', 'Verify contracts at Etherscan') .addFlag('all', 'Verify all contracts at Etherscan') @@ -55,6 +55,10 @@ task('verify:general', 'Verify contracts at Etherscan') const lendingPoolConfiguratorAddress = await addressesProvider.getLendingPoolConfigurator(); //getLendingPoolConfiguratorProxy(); const lendingPoolCollateralManagerAddress = await addressesProvider.getLendingPoolCollateralManager(); + const lendingPoolProxy = await getProxy(lendingPoolAddress); + const lendingPoolConfiguratorProxy = await getProxy(lendingPoolConfiguratorAddress); + const lendingPoolCollateralManagerProxy = await getProxy(lendingPoolCollateralManagerAddress); + if (all) { const lendingPoolImplAddress = getParamPerNetwork(LendingPool, network); const lendingPoolImpl = notFalsyOrZeroAddress(lendingPoolImplAddress) @@ -89,64 +93,69 @@ task('verify:general', 'Verify contracts at Etherscan') // Address Provider console.log('\n- Verifying address provider...\n'); - await verifyContract(addressesProvider.address, [MarketId]); + await verifyContract(eContractid.LendingPoolAddressesProvider, addressesProvider, [MarketId]); // Address Provider Registry console.log('\n- Verifying address provider registry...\n'); - await verifyContract(addressesProviderRegistry.address, []); + await verifyContract( + eContractid.LendingPoolAddressesProviderRegistry, + addressesProviderRegistry, + [] + ); // Lending Pool implementation console.log('\n- Verifying LendingPool Implementation...\n'); - await verifyContract(lendingPoolImpl.address, []); + await verifyContract(eContractid.LendingPool, lendingPoolImpl, []); // Lending Pool Configurator implementation console.log('\n- Verifying LendingPool Configurator Implementation...\n'); - await verifyContract(lendingPoolConfiguratorImpl.address, []); + await verifyContract(eContractid.LendingPoolConfigurator, lendingPoolConfiguratorImpl, []); // Lending Pool Collateral Manager implementation console.log('\n- Verifying LendingPool Collateral Manager Implementation...\n'); - await verifyContract(lendingPoolCollateralManagerImpl.address, []); + await verifyContract( + eContractid.LendingPoolCollateralManager, + lendingPoolCollateralManagerImpl, + [] + ); // Test helpers console.log('\n- Verifying Aave Provider Helpers...\n'); - await verifyContract(dataProvider.address, [addressesProvider.address]); + await verifyContract(eContractid.AaveProtocolDataProvider, dataProvider, [ + addressesProvider.address, + ]); // Wallet balance provider console.log('\n- Verifying Wallet Balance Provider...\n'); - await verifyContract(walletProvider.address, []); + await verifyContract(eContractid.WalletBalanceProvider, walletProvider, []); // WETHGateway console.log('\n- Verifying WETHGateway...\n'); - await verifyContract(wethGateway.address, [await getWethAddress(poolConfig)]); + await verifyContract(eContractid.WETHGateway, wethGateway, [ + await getWethAddress(poolConfig), + ]); } // Lending Pool proxy console.log('\n- Verifying Lending Pool Proxy...\n'); - await verifyContract(lendingPoolAddress, [addressesProvider.address]); + await verifyContract(eContractid.InitializableAdminUpgradeabilityProxy, lendingPoolProxy, [ + addressesProvider.address, + ]); // LendingPool Conf proxy console.log('\n- Verifying Lending Pool Configurator Proxy...\n'); - await verifyContract(lendingPoolConfiguratorAddress, [addressesProvider.address]); + await verifyContract( + eContractid.InitializableAdminUpgradeabilityProxy, + lendingPoolConfiguratorProxy, + [addressesProvider.address] + ); // Proxy collateral manager console.log('\n- Verifying Lending Pool Collateral Manager Proxy...\n'); - await verifyContract(lendingPoolCollateralManagerAddress, []); + await verifyContract( + eContractid.InitializableAdminUpgradeabilityProxy, + lendingPoolCollateralManagerProxy, + [] + ); - // DelegatedAwareAToken - console.log('\n- Verifying DelegatedAwareAToken...\n'); - const UNI = getParamPerNetwork(ReserveAssets, network).UNI; - const aUNI = await getAddressById('aUNI'); - if (aUNI) { - console.log('Verifying aUNI'); - await verifyContract(aUNI, [ - lendingPoolAddress, - UNI, - treasuryAddress, - 'Aave interest bearing UNI', - 'aUNI', - ZERO_ADDRESS, - ]); - } else { - console.error('Missing aUNI address at JSON DB. Skipping...'); - } console.log('Finished verifications.'); }); diff --git a/tasks/verifications/2_tokens.ts b/tasks/verifications/2_tokens.ts index 52d77ffd..eacc7f92 100644 --- a/tasks/verifications/2_tokens.ts +++ b/tasks/verifications/2_tokens.ts @@ -8,14 +8,16 @@ import { import { ZERO_ADDRESS } from '../../helpers/constants'; import { getAddressById, + getAToken, getFirstSigner, - getLendingPool, + getInterestRateStrategy, getLendingPoolAddressesProvider, - getLendingPoolConfiguratorProxy, + getProxy, + getStableDebtToken, + getVariableDebtToken, } from '../../helpers/contracts-getters'; -import { getParamPerNetwork } from '../../helpers/contracts-helpers'; -import { verifyContract } from '../../helpers/etherscan-verification'; -import { eNetwork, ICommonConfiguration, IReserveParams } from '../../helpers/types'; +import { getParamPerNetwork, verifyContract } from '../../helpers/contracts-helpers'; +import { eContractid, eNetwork, ICommonConfiguration, IReserveParams } from '../../helpers/types'; import { LendingPoolConfiguratorFactory, LendingPoolFactory } from '../../types'; task('verify:tokens', 'Deploy oracles for dev enviroment') @@ -66,27 +68,43 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') console.log; // Proxy Stable Debt console.log(`\n- Verifying Stable Debt Token proxy...\n`); - await verifyContract(stableDebtTokenAddress, [lendingPoolConfigurator.address]); + await verifyContract( + eContractid.InitializableAdminUpgradeabilityProxy, + await getProxy(stableDebtTokenAddress), + [lendingPoolConfigurator.address] + ); // Proxy Variable Debt console.log(`\n- Verifying Debt Token proxy...\n`); - await verifyContract(variableDebtTokenAddress, [lendingPoolConfigurator.address]); + await verifyContract( + eContractid.InitializableAdminUpgradeabilityProxy, + await getProxy(variableDebtTokenAddress), + [lendingPoolConfigurator.address] + ); // Proxy aToken console.log('\n- Verifying aToken proxy...\n'); - await verifyContract(aTokenAddress, [lendingPoolConfigurator.address]); + await verifyContract( + eContractid.InitializableAdminUpgradeabilityProxy, + await getProxy(aTokenAddress), + [lendingPoolConfigurator.address] + ); // Strategy Rate console.log(`\n- Verifying Strategy rate...\n`); - await verifyContract(interestRateStrategyAddress, [ - addressesProvider.address, - optimalUtilizationRate, - baseVariableBorrowRate, - variableRateSlope1, - variableRateSlope2, - stableRateSlope1, - stableRateSlope2, - ]); + await verifyContract( + eContractid.DefaultReserveInterestRateStrategy, + await getInterestRateStrategy(interestRateStrategyAddress), + [ + addressesProvider.address, + optimalUtilizationRate, + baseVariableBorrowRate, + variableRateSlope1, + variableRateSlope2, + stableRateSlope1, + stableRateSlope2, + ] + ); const stableDebt = await getAddressById(`stableDebt${token}`); const variableDebt = await getAddressById(`variableDebt${token}`); @@ -94,7 +112,7 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') if (aToken) { console.log('\n- Verifying aToken...\n'); - await verifyContract(aToken, [ + await verifyContract(eContractid.AToken, await getAToken(aToken), [ lendingPoolProxy.address, tokenAddress, treasuryAddress, @@ -107,7 +125,7 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') } if (stableDebt) { console.log('\n- Verifying StableDebtToken...\n'); - await verifyContract(stableDebt, [ + await verifyContract(eContractid.StableDebtToken, await getStableDebtToken(stableDebt), [ lendingPoolProxy.address, tokenAddress, `Aave stable debt bearing ${token}`, @@ -119,13 +137,17 @@ task('verify:tokens', 'Deploy oracles for dev enviroment') } if (variableDebt) { console.log('\n- Verifying VariableDebtToken...\n'); - await verifyContract(variableDebt, [ - lendingPoolProxy.address, - tokenAddress, - `Aave variable debt bearing ${token}`, - `variableDebt${token}`, - ZERO_ADDRESS, - ]); + await verifyContract( + eContractid.VariableDebtToken, + await getVariableDebtToken(variableDebt), + [ + lendingPoolProxy.address, + tokenAddress, + `Aave variable debt bearing ${token}`, + `variableDebt${token}`, + ZERO_ADDRESS, + ] + ); } else { console.error(`Skipping variable debt verify for ${token}. Missing address at JSON DB.`); } diff --git a/test-suites/test-aave/__setup.spec.ts b/test-suites/test-aave/__setup.spec.ts index 831b5231..dd8ed168 100644 --- a/test-suites/test-aave/__setup.spec.ts +++ b/test-suites/test-aave/__setup.spec.ts @@ -4,6 +4,7 @@ import { insertContractAddressInDb, getEthersSigners, registerContractInJsonDb, + getEthersSignersAddresses, } from '../../helpers/contracts-helpers'; import { deployLendingPoolAddressesProvider, @@ -102,9 +103,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); //setting users[1] as emergency admin, which is in position 2 in the DRE addresses list - const addressList = await Promise.all( - (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) - ); + const addressList = await getEthersSignersAddresses(); await waitForTx(await addressesProvider.setEmergencyAdmin(addressList[2])); @@ -129,6 +128,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { const lendingPoolConfiguratorProxy = await getLendingPoolConfiguratorProxy( await addressesProvider.getLendingPoolConfigurator() ); + await waitForTx(await lendingPoolConfiguratorProxy.registerRiskAdmin(addressList[3])); await insertContractAddressInDb( eContractid.LendingPoolConfigurator, lendingPoolConfiguratorProxy.address @@ -191,7 +191,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { WMATIC: mockTokens.WMATIC.address, USD: USD_ADDRESS, STAKE: mockTokens.STAKE.address, - xSUSHI: mockTokens.xSUSHI.address + xSUSHI: mockTokens.xSUSHI.address, }, fallbackOracle ); @@ -295,9 +295,9 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { before(async () => { await rawBRE.run('set-DRE'); const [deployer, secondaryWallet] = await getEthersSigners(); - const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; + const FORK = process.env.FORK; - if (MAINNET_FORK) { + if (FORK) { await rawBRE.run('aave:mainnet'); } else { console.log('-> Deploying test environment...'); diff --git a/test-suites/test-aave/borrow-cap.spec.ts b/test-suites/test-aave/borrow-cap.spec.ts new file mode 100644 index 00000000..15dd0a4d --- /dev/null +++ b/test-suites/test-aave/borrow-cap.spec.ts @@ -0,0 +1,354 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { + APPROVAL_AMOUNT_LENDING_POOL, + MAX_UINT_AMOUNT, + RAY, + MAX_BORROW_CAP, + MAX_SUPPLY_CAP, +} from '../../helpers/constants'; +import { ProtocolErrors } from '../../helpers/types'; +import { MintableERC20, WETH9, WETH9Mocked } from '../../types'; +import { parseEther } from '@ethersproject/units'; +import { BigNumber } from '@ethersproject/bignumber'; + +const { expect } = require('chai'); + +makeSuite('Borrow Cap', (testEnv: TestEnv) => { + const { VL_BORROW_CAP_EXCEEDED, RC_INVALID_BORROW_CAP } = ProtocolErrors; + + const unitParse = async (token: WETH9Mocked | MintableERC20, nb: string) => + BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3)); + it('Reserves should initially have borrow cap disabled (borrowCap = 0)', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + + const mintedAmount = parseEther('1000000000'); + // minting for main user + await dai.mint(mintedAmount); + await weth.mint(mintedAmount); + await usdc.mint(mintedAmount); + // minting for lp user + await dai.connect(user1.signer).mint(mintedAmount); + await weth.connect(user1.signer).mint(mintedAmount); + await usdc.connect(user1.signer).mint(mintedAmount); + + await dai.approve(pool.address, MAX_UINT_AMOUNT); + await weth.approve(pool.address, MAX_UINT_AMOUNT); + await usdc.approve(pool.address, MAX_UINT_AMOUNT); + await dai.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); + await weth.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); + await usdc.connect(user1.signer).approve(pool.address, MAX_UINT_AMOUNT); + + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + expect(usdcBorrowCap).to.be.equal('0'); + expect(daiBorrowCap).to.be.equal('0'); + }); + it('Should be able to borrow 10 Dai stable, 10 USDC variable', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + + const suppliedAmount = 1000; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + + const borrowedAmount = 10; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + + // deposit collateral + await pool.deposit( + weth.address, + await unitParse(weth, precisionSuppliedAmount), + deployer.address, + 0 + ); + // user 1 deposit more dai and usdc to be able to borrow + await pool + .connect(user1.signer) + .deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), user1.address, 0); + + await pool + .connect(user1.signer) + .deposit(usdc.address, await unitParse(usdc, precisionSuppliedAmount), user1.address, 0); + + // borrow + await pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 2, + 0, + deployer.address + ); + + await pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 1, + 0, + deployer.address + ); + }); + it('Sets the borrow cap for Weth and DAI to 10 Units', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + + await configurator.setBorrowCap(usdc.address, 10); + await configurator.setBorrowCap(dai.address, 10); + + const usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + const daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + expect(usdcBorrowCap).to.be.equal(10); + expect(daiBorrowCap).to.be.equal(10); + }); + it('should fail to borrow any dai or usdc, stable or variable', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 10; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + + await expect( + pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 2, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + + await expect( + pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 2, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + }); + it('Should fail to set the borrow cap for usdc and DAI to max cap + 1 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = Number(MAX_BORROW_CAP) + 1; + + await expect(configurator.setBorrowCap(usdc.address, newCap)).to.be.revertedWith( + RC_INVALID_BORROW_CAP + ); + await expect(configurator.setBorrowCap(dai.address, newCap)).to.be.revertedWith( + RC_INVALID_BORROW_CAP + ); + }); + it('Sets the borrow cap for usdc and DAI to 120 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '120'; + + await configurator.setBorrowCap(usdc.address, newCap); + await configurator.setBorrowCap(dai.address, newCap); + + const usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + const daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + expect(usdcBorrowCap).to.be.equal(newCap); + expect(daiBorrowCap).to.be.equal(newCap); + }); + it('Should succeed to borrow 10 stable dai and 10 variable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 10; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + await pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 2, + 0, + deployer.address + ); + + await pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 1, + 0, + deployer.address + ); + }); + it('should fail to borrow 100 variable dai and 100 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 100; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + + await expect( + pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 1, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + + await expect( + pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 2, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + }); + it('Should succeed to borrow 99 variable dai and 99 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 99; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + await pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 2, + 0, + deployer.address + ); + + await pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 1, + 0, + deployer.address + ); + }); + it('Raises the borrow cap for usdc and DAI to 1000 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '1000'; + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + await configurator.setBorrowCap(usdc.address, newCap); + await configurator.setBorrowCap(dai.address, newCap); + + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + expect(usdcBorrowCap).to.be.equal(newCap); + expect(daiBorrowCap).to.be.equal(newCap); + }); + it('should succeed to borrow 100 variable dai and 100 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 100; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + + await pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 1, + 0, + deployer.address + ); + + await pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 2, + 0, + deployer.address + ); + }); + it('Lowers the borrow cap for usdc and DAI to 200 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '200'; + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + await configurator.setBorrowCap(usdc.address, newCap); + await configurator.setBorrowCap(dai.address, newCap); + + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + expect(usdcBorrowCap).to.be.equal(newCap); + expect(daiBorrowCap).to.be.equal(newCap); + }); + it('should fail to borrow 100 variable dai and 100 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 100; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + + await expect( + pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 1, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + + await expect( + pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 2, + 0, + deployer.address + ) + ).to.be.revertedWith(VL_BORROW_CAP_EXCEEDED); + }); + it('Raises the borrow cap for usdc and DAI to max cap Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = MAX_BORROW_CAP; + let usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + let daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + await configurator.setBorrowCap(usdc.address, newCap); + await configurator.setBorrowCap(dai.address, newCap); + + usdcBorrowCap = (await helpersContract.getReserveCaps(usdc.address)).borrowCap; + daiBorrowCap = (await helpersContract.getReserveCaps(dai.address)).borrowCap; + + expect(usdcBorrowCap).to.be.equal(newCap); + expect(daiBorrowCap).to.be.equal(newCap); + }); + it('should succeed to borrow 100 variable dai and 100 stable usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const borrowedAmount = 100; + const precisionBorrowedAmount = (borrowedAmount * 1000).toString(); + + await pool.borrow( + usdc.address, + await unitParse(usdc, precisionBorrowedAmount), + 1, + 0, + deployer.address + ); + + await pool.borrow( + dai.address, + await unitParse(dai, precisionBorrowedAmount), + 2, + 0, + deployer.address + ); + }); +}); diff --git a/test-suites/test-aave/configurator.spec.ts b/test-suites/test-aave/configurator.spec.ts index c94dcdf8..5dc4884c 100644 --- a/test-suites/test-aave/configurator.spec.ts +++ b/test-suites/test-aave/configurator.spec.ts @@ -1,8 +1,14 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; +import { + APPROVAL_AMOUNT_LENDING_POOL, + MAX_UINT_AMOUNT, + RAY, + MAX_BORROW_CAP, +} from '../../helpers/constants'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; import { strategyWETH } from '../../markets/aave/reservesConfigs'; +import { BigNumber } from '@ethersproject/bignumber'; const { expect } = require('chai'); @@ -15,6 +21,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { RC_INVALID_LIQ_BONUS, RC_INVALID_DECIMALS, RC_INVALID_RESERVE_FACTOR, + RC_INVALID_BORROW_CAP, + RC_INVALID_SUPPLY_CAP, + LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN, + LPC_CALLER_NOT_RISK_OR_POOL_ADMIN, + VL_RESERVE_PAUSED, } = ProtocolErrors; it('Reverts trying to set an invalid reserve factor', async () => { @@ -57,8 +68,153 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); + it('Pauses the ETH reserve by pool admin', async () => { + const { configurator, weth, helpersContract, addressesProvider, users } = testEnv; + expect(await configurator.signer.getAddress()).to.be.equal( + await addressesProvider.getPoolAdmin() + ); - it('Freezes the ETH reserve', async () => { + await configurator.pauseReserve(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + + it('Unpauses the ETH reserve by pool admin ', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.unpauseReserve(weth.address); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + it('Pauses the ETH reserve by emergency admin', async () => { + const { configurator, weth, helpersContract, addressesProvider, users, emergencyAdmin } = + testEnv; + await configurator.connect(emergencyAdmin.signer).pauseReserve(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(true); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + + it('Unpauses the ETH reserve by emergency admin ', async () => { + const { configurator, helpersContract, weth, users, emergencyAdmin } = testEnv; + await configurator.connect(emergencyAdmin.signer).unpauseReserve(weth.address); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + + it('Check the only admin or emergency admin can pauseReserve ', async () => { + const { configurator, users, weth, riskAdmin } = testEnv; + await expect( + configurator.connect(riskAdmin.signer).pauseReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN); + }); + + it('Check the only admin or emergency admin can unpauseReserve ', async () => { + const { configurator, users, weth, riskAdmin } = testEnv; + await expect( + configurator.connect(riskAdmin.signer).unpauseReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN); + }); + + it('Freezes the ETH reserve by pool Admin', async () => { const { configurator, weth, helpersContract } = testEnv; await configurator.freezeReserve(weth.address); @@ -73,9 +229,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(true); expect(decimals).to.be.equal(strategyWETH.reserveDecimals); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); @@ -83,9 +242,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Unfreezes the ETH reserve', async () => { + it('Unfreezes the ETH reserve by Pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.unfreezeReserve(weth.address); @@ -100,9 +261,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(false); expect(decimals).to.be.equal(strategyWETH.reserveDecimals); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); @@ -110,25 +274,90 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + it('Freezes the ETH reserve by Risk Admin', async () => { + const { configurator, weth, helpersContract, riskAdmin } = testEnv; + + await configurator.connect(riskAdmin.signer).freezeReserve(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(true); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Check the onlyAaveAdmin on freezeReserve ', async () => { - const { configurator, users, weth } = testEnv; + it('Unfreezes the ETH reserve by Risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator.connect(riskAdmin.signer).unfreezeReserve(weth.address); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + + it('Check the onlyRiskOrPoolAdmins on freezeReserve ', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; await expect( - configurator.connect(users[2].signer).freezeReserve(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + configurator.connect(emergencyAdmin.signer).freezeReserve(weth.address), + LPC_CALLER_NOT_RISK_OR_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); }); - it('Check the onlyAaveAdmin on unfreezeReserve ', async () => { - const { configurator, users, weth } = testEnv; + it('Check the onlyRiskOrPoolAdmins on unfreezeReserve ', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; await expect( - configurator.connect(users[2].signer).unfreezeReserve(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + configurator.connect(emergencyAdmin.signer).unfreezeReserve(weth.address), + LPC_CALLER_NOT_RISK_OR_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); }); - it('Deactivates the ETH reserve for borrowing', async () => { + it('Deactivates the ETH reserve for borrowing via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.disableBorrowingOnReserve(weth.address); const { @@ -142,9 +371,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(false); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(false); expect(decimals).to.be.equal(strategyWETH.reserveDecimals); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); @@ -152,11 +384,13 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Activates the ETH reserve for borrowing', async () => { + it('Activates the ETH reserve for borrowing via pool admin', async () => { const { configurator, weth, helpersContract } = testEnv; - await configurator.enableBorrowingOnReserve(weth.address, true); + await configurator.enableBorrowingOnReserve(weth.address, '0', true); const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); const { @@ -170,9 +404,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(false); expect(decimals).to.be.equal(strategyWETH.reserveDecimals); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); @@ -180,27 +417,98 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); expect(variableBorrowIndex.toString()).to.be.equal(RAY); }); - it('Check the onlyAaveAdmin on disableBorrowingOnReserve ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).disableBorrowingOnReserve(weth.address), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + it('Deactivates the ETH reserve for borrowing via risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator.connect(riskAdmin.signer).disableBorrowingOnReserve(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(false); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + it('Activates the ETH reserve for borrowing via risk admin', async () => { + const { configurator, weth, helpersContract, riskAdmin } = testEnv; + await configurator.connect(riskAdmin.signer).enableBorrowingOnReserve(weth.address, '0', true); + const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + + expect(variableBorrowIndex.toString()).to.be.equal(RAY); }); - it('Deactivates the ETH reserve as collateral', async () => { + it('Check the onlyAaveAdmin or Risk admin on disableBorrowingOnReserve ', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; + + await expect( + configurator.connect(emergencyAdmin.signer).disableBorrowingOnReserve(weth.address), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); + }); + + it('Check the onlyAaveAdmin or Risk admin on enableBorrowingOnReserve ', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; + await expect( + configurator + .connect(emergencyAdmin.signer) + .enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); + }); + + it('Deactivates the ETH reserve as collateral via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.configureReserveAsCollateral(weth.address, 0, 0, 0); @@ -215,9 +523,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(false); expect(decimals).to.be.equal(18); expect(ltv).to.be.equal(0); @@ -225,9 +536,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(0); expect(stableBorrowRateEnabled).to.be.equal(true); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Activates the ETH reserve as collateral', async () => { + it('Activates the ETH reserve as collateral via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.configureReserveAsCollateral(weth.address, '8000', '8250', '10500'); @@ -242,9 +555,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(false); expect(decimals).to.be.equal(strategyWETH.reserveDecimals); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); @@ -252,19 +568,88 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + it('Deactivates the ETH reserve as collateral via risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator + .connect(riskAdmin.signer) + .configureReserveAsCollateral(weth.address, 0, 0, 0); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(18); + expect(ltv).to.be.equal(0); + expect(liquidationThreshold).to.be.equal(0); + expect(liquidationBonus).to.be.equal(0); + expect(stableBorrowRateEnabled).to.be.equal(true); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Check the onlyAaveAdmin on configureReserveAsCollateral ', async () => { - const { configurator, users, weth } = testEnv; + it('Activates the ETH reserve as collateral via risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator + .connect(riskAdmin.signer) + .configureReserveAsCollateral(weth.address, '8000', '8250', '10500'); + + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + + it('Check the onlyRiskOrPoolAdmin on configureReserveAsCollateral ', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; await expect( configurator - .connect(users[2].signer) + .connect(emergencyAdmin.signer) .configureReserveAsCollateral(weth.address, '7500', '8000', '10500'), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); }); - it('Disable stable borrow rate on the ETH reserve', async () => { + it('Disable stable borrow rate on the ETH reserve via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.disableReserveStableRate(weth.address); const { @@ -278,9 +663,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(false); expect(decimals).to.be.equal(strategyWETH.reserveDecimals); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); @@ -288,9 +676,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(false); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Enables stable borrow rate on the ETH reserve', async () => { + it('Enables stable borrow rate on the ETH reserve via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.enableReserveStableRate(weth.address); const { @@ -304,9 +694,12 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(false); expect(decimals).to.be.equal(strategyWETH.reserveDecimals); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); @@ -314,25 +707,111 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(true); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + it('Disable stable borrow rate on the ETH reserve risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator.connect(riskAdmin.signer).disableReserveStableRate(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(false); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Check the onlyAaveAdmin on disableReserveStableRate', async () => { - const { configurator, users, weth } = testEnv; + it('Enables stable borrow rate on the ETH reserve risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator.connect(riskAdmin.signer).enableReserveStableRate(weth.address); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(true); + expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + + it('Check the onlyRiskOrPoolAdmin on disableReserveStableRate', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; await expect( - configurator.connect(users[2].signer).disableReserveStableRate(weth.address), + configurator.connect(emergencyAdmin.signer).disableReserveStableRate(weth.address), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); }); - it('Check the onlyAaveAdmin on enableReserveStableRate', async () => { - const { configurator, users, weth } = testEnv; + it('Check the onlyRiskOrPoolAdmin on enableReserveStableRate', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; await expect( - configurator.connect(users[2].signer).enableReserveStableRate(weth.address), + configurator.connect(emergencyAdmin.signer).enableReserveStableRate(weth.address), CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); }); - it('Changes the reserve factor of WETH', async () => { + it('Check the onlyRiskOrPoolAdmin on setReserveFactor', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; + await expect( + configurator.connect(emergencyAdmin.signer).setReserveFactor(weth.address, '1000'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); + }); + + it('Check the onlyRiskOrPoolAdmin on setBorrowCap', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; + await expect( + configurator.connect(emergencyAdmin.signer).setBorrowCap(weth.address, '3000000000'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); + }); + it('Check the onlyRiskOrPoolAdmin on setSupplyCap', async () => { + const { configurator, users, weth, emergencyAdmin } = testEnv; + await expect( + configurator.connect(emergencyAdmin.signer).setSupplyCap(weth.address, '3000000000'), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(LPC_CALLER_NOT_RISK_OR_POOL_ADMIN); + }); + + it('Changes the reserve factor of WETH via pool admin', async () => { const { configurator, helpersContract, weth } = testEnv; await configurator.setReserveFactor(weth.address, '1000'); const { @@ -346,9 +825,88 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { isActive, isFrozen, } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); expect(borrowingEnabled).to.be.equal(true); expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + expect(reserveFactor).to.be.equal(1000); + }); + it('Changes the reserve factor of WETH risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator.connect(riskAdmin.signer).setReserveFactor(weth.address, '1000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(borrowCap).to.be.equal(strategyWETH.borrowCap); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + expect(reserveFactor).to.be.equal(1000); + }); + + it('Check that borrowCap cannot be set to value that exceeds the MAX_BORROW_CAP', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.setBorrowCap(weth.address, BigNumber.from(MAX_BORROW_CAP).add(1)), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(RC_INVALID_BORROW_CAP); + }); + it('Check that supplyCap cannot be set to value that exceeds the MAX_SUPPLY_CAP', async () => { + const { configurator, users, weth } = testEnv; + await expect( + configurator.setSupplyCap(weth.address, BigNumber.from(MAX_BORROW_CAP).add(1)), + CALLER_NOT_POOL_ADMIN + ).to.be.revertedWith(RC_INVALID_SUPPLY_CAP); + }); + + it('Changes the borrow Cap of WETH via pool admin', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.setBorrowCap(weth.address, '3000000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); expect(isFrozen).to.be.equal(false); expect(decimals).to.be.equal(strategyWETH.reserveDecimals); expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); @@ -356,14 +914,99 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); expect(reserveFactor).to.be.equal(1000); + expect(borrowCap).to.be.equal('3000000'); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); + }); + it('Changes the borrow Cap of WETH risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator.connect(riskAdmin.signer).setBorrowCap(weth.address, '3000000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(1000); + expect(borrowCap).to.be.equal('3000000'); + expect(supplyCap).to.be.equal(strategyWETH.supplyCap); }); - it('Check the onlyLendingPoolManager on setReserveFactor', async () => { - const { configurator, users, weth } = testEnv; - await expect( - configurator.connect(users[2].signer).setReserveFactor(weth.address, '2000'), - CALLER_NOT_POOL_ADMIN - ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); + it('Changes the supply Cap of WETH via pool admin', async () => { + const { configurator, helpersContract, weth } = testEnv; + await configurator.setSupplyCap(weth.address, '3000000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(1000); + expect(borrowCap).to.be.equal('3000000'); + expect(supplyCap).to.be.equal('3000000'); + }); + it('Changes the supply Cap of WETH via risk admin', async () => { + const { configurator, helpersContract, weth, riskAdmin } = testEnv; + await configurator.connect(riskAdmin.signer).setSupplyCap(weth.address, '3000000'); + const { + decimals, + ltv, + liquidationBonus, + liquidationThreshold, + reserveFactor, + stableBorrowRateEnabled, + borrowingEnabled, + isActive, + isFrozen, + } = await helpersContract.getReserveConfigurationData(weth.address); + const { borrowCap, supplyCap } = await helpersContract.getReserveCaps(weth.address); + const isPaused = await helpersContract.getPaused(weth.address); + + expect(borrowingEnabled).to.be.equal(true); + expect(isActive).to.be.equal(true); + expect(isPaused).to.be.equal(false); + expect(isFrozen).to.be.equal(false); + expect(decimals).to.be.equal(strategyWETH.reserveDecimals); + expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); + expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); + expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); + expect(stableBorrowRateEnabled).to.be.equal(strategyWETH.stableBorrowRateEnabled); + expect(reserveFactor).to.be.equal(1000); + expect(borrowCap).to.be.equal('3000000'); + expect(supplyCap).to.be.equal('3000000'); }); it('Reverts when trying to disable the DAI reserve with liquidity on it', async () => { @@ -383,4 +1026,23 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { LPC_RESERVE_LIQUIDITY_NOT_0 ).to.be.revertedWith(LPC_RESERVE_LIQUIDITY_NOT_0); }); + it('Register a new risk Admin', async () => { + const { dai, pool, configurator, users, riskAdmin } = testEnv; + await configurator.registerRiskAdmin(users[3].address); + + const isRiskAdminRegistered = await configurator.isRiskAdmin(riskAdmin.address); + const isNewRegistered = await configurator.isRiskAdmin(users[3].address); + expect(isNewRegistered).to.be.true; + expect(isRiskAdminRegistered).to.be.true; + }); + it('Unregister a risk Admins', async () => { + const { dai, pool, configurator, users, riskAdmin } = testEnv; + await configurator.unregisterRiskAdmin(users[3].address); + await configurator.unregisterRiskAdmin(riskAdmin.address); + + const isRiskAdminRegistered = await configurator.isRiskAdmin(riskAdmin.address); + const isNewRegistered = await configurator.isRiskAdmin(users[3].address); + expect(isNewRegistered).to.be.false; + expect(isRiskAdminRegistered).to.be.false; + }); }); diff --git a/test-suites/test-aave/helpers/make-suite.ts b/test-suites/test-aave/helpers/make-suite.ts index e56358be..490aeb0b 100644 --- a/test-suites/test-aave/helpers/make-suite.ts +++ b/test-suites/test-aave/helpers/make-suite.ts @@ -15,7 +15,7 @@ import { getUniswapRepayAdapter, getFlashLiquidationAdapter, } from '../../../helpers/contracts-getters'; -import { eEthereumNetwork, tEthereumAddress } from '../../../helpers/types'; +import { eEthereumNetwork, eNetwork, tEthereumAddress } from '../../../helpers/types'; import { LendingPool } from '../../../types/LendingPool'; import { AaveProtocolDataProvider } from '../../../types/AaveProtocolDataProvider'; import { MintableERC20 } from '../../../types/MintableERC20'; @@ -51,6 +51,9 @@ export interface SignerWithAddress { } export interface TestEnv { deployer: SignerWithAddress; + poolAdmin: SignerWithAddress; + emergencyAdmin: SignerWithAddress; + riskAdmin: SignerWithAddress; users: SignerWithAddress[]; pool: LendingPool; configurator: LendingPoolConfigurator; @@ -77,6 +80,9 @@ const setBuidlerevmSnapshotId = (id: string) => { const testEnv: TestEnv = { deployer: {} as SignerWithAddress, + poolAdmin: {} as SignerWithAddress, + emergencyAdmin: {} as SignerWithAddress, + riskAdmin: {} as SignerWithAddress, users: [] as SignerWithAddress[], pool: {} as LendingPool, configurator: {} as LendingPoolConfigurator, @@ -110,15 +116,18 @@ export async function initializeMakeSuite() { }); } testEnv.deployer = deployer; + testEnv.poolAdmin = deployer; + testEnv.emergencyAdmin = testEnv.users[1]; + testEnv.riskAdmin = testEnv.users[2]; testEnv.pool = await getLendingPool(); testEnv.configurator = await getLendingPoolConfiguratorProxy(); testEnv.addressesProvider = await getLendingPoolAddressesProvider(); - if (process.env.MAINNET_FORK === 'true') { + if (process.env.FORK) { testEnv.registry = await getLendingPoolAddressesProviderRegistry( - getParamPerNetwork(AaveConfig.ProviderRegistry, eEthereumNetwork.main) + getParamPerNetwork(AaveConfig.ProviderRegistry, process.env.FORK as eNetwork) ); } else { testEnv.registry = await getLendingPoolAddressesProviderRegistry(); @@ -163,7 +172,7 @@ export async function initializeMakeSuite() { const setSnapshot = async () => { const hre = DRE as HardhatRuntimeEnvironment; if (usingTenderly()) { - setBuidlerevmSnapshotId((await hre.tenderlyRPC.getHead()) || '0x1'); + setBuidlerevmSnapshotId((await hre.tenderlyNetwork.getHead()) || '0x1'); return; } setBuidlerevmSnapshotId(await evmSnapshot()); @@ -172,7 +181,7 @@ const setSnapshot = async () => { const revertHead = async () => { const hre = DRE as HardhatRuntimeEnvironment; if (usingTenderly()) { - await hre.tenderlyRPC.setHead(buidlerevmSnapshotId); + await hre.tenderlyNetwork.setHead(buidlerevmSnapshotId); return; } await evmRevert(buidlerevmSnapshotId); diff --git a/test-suites/test-aave/pausable-functions.spec.ts b/test-suites/test-aave/pausable-functions.spec.ts index c95aaf3c..24bedb69 100644 --- a/test-suites/test-aave/pausable-functions.spec.ts +++ b/test-suites/test-aave/pausable-functions.spec.ts @@ -12,17 +12,14 @@ const { expect } = require('chai'); makeSuite('Pausable Pool', (testEnv: TestEnv) => { let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; - const { - LP_IS_PAUSED, - INVALID_FROM_BALANCE_AFTER_TRANSFER, - INVALID_TO_BALANCE_AFTER_TRANSFER, - } = ProtocolErrors; + const { LP_IS_PAUSED, INVALID_FROM_BALANCE_AFTER_TRANSFER, INVALID_TO_BALANCE_AFTER_TRANSFER } = + ProtocolErrors; before(async () => { _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); }); - it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succees', async () => { + it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succeeds', async () => { const { users, pool, dai, aDai, configurator } = testEnv; const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); diff --git a/test-suites/test-aave/reserve-pause.spec.ts b/test-suites/test-aave/reserve-pause.spec.ts new file mode 100644 index 00000000..22851764 --- /dev/null +++ b/test-suites/test-aave/reserve-pause.spec.ts @@ -0,0 +1,330 @@ +import { makeSuite, TestEnv } from './helpers/make-suite'; +import { ProtocolErrors, RateMode } from '../../helpers/types'; +import { APPROVAL_AMOUNT_LENDING_POOL, oneEther } from '../../helpers/constants'; +import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; +import { parseEther, parseUnits } from 'ethers/lib/utils'; +import { BigNumber } from 'bignumber.js'; +import { MockFlashLoanReceiver } from '../../types/MockFlashLoanReceiver'; +import { getMockFlashLoanReceiver } from '../../helpers/contracts-getters'; + +const { expect } = require('chai'); + +makeSuite('Pause Reserve', (testEnv: TestEnv) => { + let _mockFlashLoanReceiver = {} as MockFlashLoanReceiver; + + const { + VL_RESERVE_PAUSED, + INVALID_FROM_BALANCE_AFTER_TRANSFER, + INVALID_TO_BALANCE_AFTER_TRANSFER, + } = ProtocolErrors; + + before(async () => { + _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); + }); + + it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succeeds', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool + .connect(users[0].signer) + .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); + + const user0Balance = await aDai.balanceOf(users[0].address); + const user1Balance = await aDai.balanceOf(users[1].address); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).pauseReserve(dai.address); + + // User 0 tries the transfer to User 1 + await expect( + aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit) + ).to.revertedWith(VL_RESERVE_PAUSED); + + const pausedFromBalance = await aDai.balanceOf(users[0].address); + const pausedToBalance = await aDai.balanceOf(users[1].address); + + expect(pausedFromBalance).to.be.equal( + user0Balance.toString(), + INVALID_TO_BALANCE_AFTER_TRANSFER + ); + expect(pausedToBalance.toString()).to.be.equal( + user1Balance.toString(), + INVALID_FROM_BALANCE_AFTER_TRANSFER + ); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).unpauseReserve(dai.address); + + // User 0 succeeds transfer to User 1 + await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit); + + const fromBalance = await aDai.balanceOf(users[0].address); + const toBalance = await aDai.balanceOf(users[1].address); + + expect(fromBalance.toString()).to.be.equal( + user0Balance.sub(amountDAItoDeposit), + INVALID_FROM_BALANCE_AFTER_TRANSFER + ); + expect(toBalance.toString()).to.be.equal( + user1Balance.add(amountDAItoDeposit), + INVALID_TO_BALANCE_AFTER_TRANSFER + ); + }); + + it('Deposit', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).pauseReserve(dai.address); + await expect( + pool.connect(users[0].signer).deposit(dai.address, amountDAItoDeposit, users[0].address, '0') + ).to.revertedWith(VL_RESERVE_PAUSED); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).unpauseReserve(dai.address); + }); + + it('Withdraw', async () => { + const { users, pool, dai, aDai, configurator } = testEnv; + + const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); + + await dai.connect(users[0].signer).mint(amountDAItoDeposit); + + // user 0 deposits 1000 DAI + await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool + .connect(users[0].signer) + .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); + + // Configurator pauses the pool + await configurator.connect(users[1].signer).pauseReserve(dai.address); + + // user tries to burn + await expect( + pool.connect(users[0].signer).withdraw(dai.address, amountDAItoDeposit, users[0].address) + ).to.revertedWith(VL_RESERVE_PAUSED); + + // Configurator unpauses the pool + await configurator.connect(users[1].signer).unpauseReserve(dai.address); + }); + + it('Borrow', async () => { + const { pool, dai, users, configurator } = testEnv; + + const user = users[1]; + // Pause the pool + await configurator.connect(users[1].signer).pauseReserve(dai.address); + + // Try to execute liquidation + await expect( + pool.connect(user.signer).borrow(dai.address, '1', '1', '0', user.address) + ).revertedWith(VL_RESERVE_PAUSED); + + // Unpause the pool + await configurator.connect(users[1].signer).unpauseReserve(dai.address); + }); + + it('Repay', async () => { + const { pool, dai, users, configurator } = testEnv; + + const user = users[1]; + // Pause the pool + await configurator.connect(users[1].signer).pauseReserve(dai.address); + + // Try to execute liquidation + await expect(pool.connect(user.signer).repay(dai.address, '1', '1', user.address)).revertedWith( + VL_RESERVE_PAUSED + ); + + // Unpause the pool + await configurator.connect(users[1].signer).unpauseReserve(dai.address); + }); + + it('Flash loan', async () => { + const { dai, pool, weth, users, configurator } = testEnv; + + const caller = users[3]; + + const flashAmount = parseEther('0.8'); + + await _mockFlashLoanReceiver.setFailExecutionTransfer(true); + + // Pause pool + await configurator.connect(users[1].signer).pauseReserve(weth.address); + + await expect( + pool + .connect(caller.signer) + .flashLoan( + _mockFlashLoanReceiver.address, + [weth.address], + [flashAmount], + [1], + caller.address, + '0x10', + '0' + ) + ).revertedWith(VL_RESERVE_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).unpauseReserve(weth.address); + }); + + it('Liquidation call', async () => { + const { users, pool, usdc, oracle, weth, configurator, helpersContract } = testEnv; + const depositor = users[3]; + const borrower = users[4]; + + //mints USDC to depositor + await usdc + .connect(depositor.signer) + .mint(await convertToCurrencyDecimals(usdc.address, '1000')); + + //approve protocol to access depositor wallet + await usdc.connect(depositor.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + //user 3 deposits 1000 USDC + const amountUSDCtoDeposit = await convertToCurrencyDecimals(usdc.address, '1000'); + + await pool + .connect(depositor.signer) + .deposit(usdc.address, amountUSDCtoDeposit, depositor.address, '0'); + + //user 4 deposits 1 ETH + const amountETHtoDeposit = await convertToCurrencyDecimals(weth.address, '1'); + + //mints WETH to borrower + await weth.connect(borrower.signer).mint(amountETHtoDeposit); + + //approve protocol to access borrower wallet + await weth.connect(borrower.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + await pool + .connect(borrower.signer) + .deposit(weth.address, amountETHtoDeposit, borrower.address, '0'); + + //user 4 borrows + const userGlobalData = await pool.getUserAccountData(borrower.address); + + const usdcPrice = await oracle.getAssetPrice(usdc.address); + + const amountUSDCToBorrow = await convertToCurrencyDecimals( + usdc.address, + new BigNumber(userGlobalData.availableBorrowsETH.toString()) + .div(usdcPrice.toString()) + .multipliedBy(0.9502) + .toFixed(0) + ); + + await pool + .connect(borrower.signer) + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); + + // Drops HF below 1 + await oracle.setAssetPrice( + usdc.address, + new BigNumber(usdcPrice.toString()).multipliedBy(1.2).toFixed(0) + ); + + //mints dai to the liquidator + await usdc.mint(await convertToCurrencyDecimals(usdc.address, '1000')); + await usdc.approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + + const userReserveDataBefore = await helpersContract.getUserReserveData( + usdc.address, + borrower.address + ); + + const amountToLiquidate = new BigNumber(userReserveDataBefore.currentStableDebt.toString()) + .multipliedBy(0.5) + .toFixed(0); + + // Pause pool + await configurator.connect(users[1].signer).pauseReserve(usdc.address); + + // Do liquidation + await expect( + pool.liquidationCall(weth.address, usdc.address, borrower.address, amountToLiquidate, true) + ).revertedWith(VL_RESERVE_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).unpauseReserve(usdc.address); + }); + + it('SwapBorrowRateMode', async () => { + const { pool, weth, dai, usdc, users, configurator } = testEnv; + const user = users[1]; + const amountWETHToDeposit = parseEther('10'); + const amountDAIToDeposit = parseEther('120'); + const amountToBorrow = parseUnits('65', 6); + + await weth.connect(user.signer).mint(amountWETHToDeposit); + await weth.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); + + await dai.connect(user.signer).mint(amountDAIToDeposit); + await dai.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(dai.address, amountDAIToDeposit, user.address, '0'); + + await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); + + // Pause pool + await configurator.connect(users[1].signer).pauseReserve(usdc.address); + + // Try to repay + await expect( + pool.connect(user.signer).swapBorrowRateMode(usdc.address, RateMode.Stable) + ).revertedWith(VL_RESERVE_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).unpauseReserve(usdc.address); + }); + + it('RebalanceStableBorrowRate', async () => { + const { pool, dai, users, configurator } = testEnv; + const user = users[1]; + // Pause pool + await configurator.connect(users[1].signer).pauseReserve(dai.address); + + await expect( + pool.connect(user.signer).rebalanceStableBorrowRate(dai.address, user.address) + ).revertedWith(VL_RESERVE_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).unpauseReserve(dai.address); + }); + + it('setUserUseReserveAsCollateral', async () => { + const { pool, weth, users, configurator } = testEnv; + const user = users[1]; + + const amountWETHToDeposit = parseEther('1'); + await weth.connect(user.signer).mint(amountWETHToDeposit); + await weth.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); + await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); + + // Pause pool + await configurator.connect(users[1].signer).pauseReserve(weth.address); + + await expect( + pool.connect(user.signer).setUserUseReserveAsCollateral(weth.address, false) + ).revertedWith(VL_RESERVE_PAUSED); + + // Unpause pool + await configurator.connect(users[1].signer).unpauseReserve(weth.address); + }); +}); diff --git a/test-suites/test-aave/supply-cap.spec.ts b/test-suites/test-aave/supply-cap.spec.ts new file mode 100644 index 00000000..6c213682 --- /dev/null +++ b/test-suites/test-aave/supply-cap.spec.ts @@ -0,0 +1,299 @@ +import { TestEnv, makeSuite } from './helpers/make-suite'; +import { + APPROVAL_AMOUNT_LENDING_POOL, + MAX_UINT_AMOUNT, + RAY, + MAX_SUPPLY_CAP, +} from '../../helpers/constants'; +import { ProtocolErrors } from '../../helpers/types'; +import { MintableERC20, WETH9, WETH9Mocked } from '../../types'; +import { parseEther } from '@ethersproject/units'; +import { BigNumber } from '@ethersproject/bignumber'; + +const { expect } = require('chai'); + +makeSuite('supply Cap', (testEnv: TestEnv) => { + const { VL_SUPPLY_CAP_EXCEEDED, RC_INVALID_SUPPLY_CAP } = ProtocolErrors; + + const unitParse = async (token: WETH9Mocked | MintableERC20, nb: string) => + BigNumber.from(nb).mul(BigNumber.from('10').pow((await token.decimals()) - 3)); + + it('Reserves should initially have supply cap disabled (supplyCap = 0)', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + + const mintedAmount = parseEther('1000000000'); + await dai.mint(mintedAmount); + await weth.mint(mintedAmount); + await usdc.mint(mintedAmount); + + await dai.approve(pool.address, MAX_UINT_AMOUNT); + await weth.approve(pool.address, MAX_UINT_AMOUNT); + await usdc.approve(pool.address, MAX_UINT_AMOUNT); + + let usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcSupplyCap).to.be.equal('0'); + expect(daiSupplyCap).to.be.equal('0'); + }); + it('Should be able to deposit 1000 Dai, 1000 USDC and 1000 Weth', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + + const suppliedAmount = 1000; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + + await pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await unitParse(dai, precisionSuppliedAmount), + deployer.address, + 0 + ); + await pool.deposit( + weth.address, + await unitParse(weth, precisionSuppliedAmount), + deployer.address, + 0 + ); + }); + it('Sets the supply cap for Weth and DAI to 1000 Unit', async () => { + const { + configurator, + weth, + pool, + dai, + usdc, + deployer, + helpersContract, + users: [user1], + } = testEnv; + + const newCap = '1000'; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + const usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + const daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); + }); + it('should fail to supply any dai or usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 10; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + + await expect( + pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + + await expect( + pool.deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), deployer.address, 0) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + }); + it('Should fail to set the supply cap for usdc and DAI to max cap + 1 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = Number(MAX_SUPPLY_CAP) + 1; + + await expect(configurator.setSupplyCap(usdc.address, newCap)).to.be.revertedWith( + RC_INVALID_SUPPLY_CAP + ); + await expect(configurator.setSupplyCap(dai.address, newCap)).to.be.revertedWith( + RC_INVALID_SUPPLY_CAP + ); + }); + it('Sets the supply cap for usdc and DAI to 1110 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '1110'; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + const usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + const daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); + }); + it('Should succeed to supply 10 dai and 10 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 10; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + await pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await unitParse(dai, precisionSuppliedAmount), + deployer.address, + 0 + ); + }); + it('should fail to supply 100 dai and 100 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 100; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + + await expect( + pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + + await expect( + pool.deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), deployer.address, 0) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + }); + it('Should succeed to supply 99 dai and 99 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 99; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + await pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await unitParse(dai, precisionSuppliedAmount), + deployer.address, + 0 + ); + }); + it('Raises the supply cap for usdc and DAI to 2000 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '2000'; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + const usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + const daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); + }); + it('should succeed to supply 100 dai and 100 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 100; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + await pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await unitParse(dai, precisionSuppliedAmount), + deployer.address, + 0 + ); + }); + it('Lowers the supply cap for usdc and DAI to 1200 Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = '1200'; + let usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); + }); + it('should fail to supply 100 dai and 100 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 100; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + + await expect( + pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + + await expect( + pool.deposit(dai.address, await unitParse(dai, precisionSuppliedAmount), deployer.address, 0) + ).to.be.revertedWith(VL_SUPPLY_CAP_EXCEEDED); + }); + it('Raises the supply cap for usdc and DAI to max cap Units', async () => { + const { configurator, usdc, pool, dai, deployer, helpersContract } = testEnv; + const newCap = MAX_SUPPLY_CAP; + let usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + let daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + await configurator.setSupplyCap(usdc.address, newCap); + await configurator.setSupplyCap(dai.address, newCap); + + usdcSupplyCap = (await helpersContract.getReserveCaps(usdc.address)).supplyCap; + daiSupplyCap = (await helpersContract.getReserveCaps(dai.address)).supplyCap; + + expect(usdcSupplyCap).to.be.equal(newCap); + expect(daiSupplyCap).to.be.equal(newCap); + }); + it('should succeed to supply 100 dai and 100 usdc', async () => { + const { usdc, pool, dai, deployer, helpersContract } = testEnv; + const suppliedAmount = 100; + const precisionSuppliedAmount = (suppliedAmount * 1000).toString(); + await pool.deposit( + usdc.address, + await unitParse(usdc, precisionSuppliedAmount), + deployer.address, + 0 + ); + + await pool.deposit( + dai.address, + await unitParse(dai, precisionSuppliedAmount), + deployer.address, + 0 + ); + }); +}); diff --git a/test-suites/test-aave/uniswapAdapters.liquiditySwap.spec.ts b/test-suites/test-aave/uniswapAdapters.liquiditySwap.spec.ts index 42224c52..e9883776 100644 --- a/test-suites/test-aave/uniswapAdapters.liquiditySwap.spec.ts +++ b/test-suites/test-aave/uniswapAdapters.liquiditySwap.spec.ts @@ -187,17 +187,12 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const collateralDecimals = (await usdc.decimals()).toString(); const principalDecimals = (await dai.decimals()).toString(); - const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); + const expectedDaiAmountForUsdc = new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))) + .toFixed(0); // Make a deposit for user await usdc.connect(user).mint(amountUSDCtoSwap); @@ -240,7 +235,6 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { ], [false, false] ); - await pool .connect(user) .flashLoan( @@ -309,17 +303,12 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const collateralDecimals = (await usdc.decimals()).toString(); const principalDecimals = (await dai.decimals()).toString(); - const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); + const expectedDaiAmountForUsdc = new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))) + .toFixed(0); // Make a deposit for user await usdc.connect(user).mint(amountUSDCtoSwap); @@ -862,17 +851,12 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const collateralDecimals = (await usdc.decimals()).toString(); const principalDecimals = (await dai.decimals()).toString(); - const expectedDaiAmount = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); + const expectedDaiAmount = new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))) + .toFixed(0); await mockUniswapRouter.connect(user).setAmountToReturn(usdc.address, expectedDaiAmount); @@ -1484,17 +1468,12 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const collateralDecimals = (await usdc.decimals()).toString(); const principalDecimals = (await dai.decimals()).toString(); - const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); + const expectedDaiAmountForUsdc = new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))) + .toFixed(0); // Make a deposit for user await usdc.connect(user).mint(amountUSDCtoSwap); @@ -1592,17 +1571,12 @@ makeSuite('Uniswap adapters', (testEnv: TestEnv) => { const collateralDecimals = (await usdc.decimals()).toString(); const principalDecimals = (await dai.decimals()).toString(); - const expectedDaiAmountForUsdc = await convertToCurrencyDecimals( - dai.address, - new BigNumber(amountUSDCtoSwap.toString()) - .times( - new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) - ) - .div( - new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals)) - ) - .toFixed(0) - ); + const expectedDaiAmountForUsdc = new BigNumber(amountUSDCtoSwap.toString()) + .times( + new BigNumber(usdcPrice.toString()).times(new BigNumber(10).pow(principalDecimals)) + ) + .div(new BigNumber(daiPrice.toString()).times(new BigNumber(10).pow(collateralDecimals))) + .toFixed(0); // Make a deposit for user await usdc.connect(user).mint(amountUSDCtoSwap); diff --git a/test-suites/test-amm/__setup.spec.ts b/test-suites/test-amm/__setup.spec.ts index 277998f4..0fae3acd 100644 --- a/test-suites/test-amm/__setup.spec.ts +++ b/test-suites/test-amm/__setup.spec.ts @@ -4,6 +4,7 @@ import { insertContractAddressInDb, getEthersSigners, registerContractInJsonDb, + getEthersSignersAddresses, } from '../../helpers/contracts-helpers'; import { deployLendingPoolAddressesProvider, @@ -26,7 +27,7 @@ import { deployUniswapLiquiditySwapAdapter, deployUniswapRepayAdapter, deployFlashLiquidationAdapter, - authorizeWETHGateway + authorizeWETHGateway, } from '../../helpers/contracts-deployments'; import { Signer } from 'ethers'; import { TokenContractId, eContractid, tEthereumAddress, AavePools } from '../../helpers/types'; @@ -101,9 +102,7 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { await waitForTx(await addressesProvider.setPoolAdmin(aaveAdmin)); //setting users[1] as emergency admin, which is in position 2 in the DRE addresses list - const addressList = await Promise.all( - (await DRE.ethers.getSigners()).map((signer) => signer.getAddress()) - ); + const addressList = await getEthersSignersAddresses(); await waitForTx(await addressesProvider.setEmergencyAdmin(addressList[2])); @@ -240,8 +239,8 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { console.log('Initialize configuration'); const config = loadPoolConfig(ConfigNames.Amm); - - const { + + const { ATokenNamePrefix, StableDebtTokenNamePrefix, VariableDebtTokenNamePrefix, @@ -292,9 +291,9 @@ const buildTestEnv = async (deployer: Signer, secondaryWallet: Signer) => { before(async () => { await rawBRE.run('set-DRE'); const [deployer, secondaryWallet] = await getEthersSigners(); - const MAINNET_FORK = process.env.MAINNET_FORK === 'true'; + const FORK = process.env.FORK; - if (MAINNET_FORK) { + if (FORK) { await rawBRE.run('amm:mainnet'); } else { console.log('-> Deploying test environment...'); diff --git a/test-suites/test-amm/configurator.spec.ts b/test-suites/test-amm/configurator.spec.ts index e4e3f4fa..6370ce1c 100644 --- a/test-suites/test-amm/configurator.spec.ts +++ b/test-suites/test-amm/configurator.spec.ts @@ -1,5 +1,5 @@ import { TestEnv, makeSuite } from './helpers/make-suite'; -import { APPROVAL_AMOUNT_LENDING_POOL, RAY } from '../../helpers/constants'; +import { APPROVAL_AMOUNT_LENDING_POOL, MAX_BORROW_CAP, RAY } from '../../helpers/constants'; import { convertToCurrencyDecimals } from '../../helpers/contracts-helpers'; import { ProtocolErrors } from '../../helpers/types'; import { strategyWETH } from '../../markets/amm/reservesConfigs'; @@ -156,7 +156,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Activates the ETH reserve for borrowing', async () => { const { configurator, weth, helpersContract } = testEnv; - await configurator.enableBorrowingOnReserve(weth.address, true); + await configurator.enableBorrowingOnReserve(weth.address, '0', true); const { variableBorrowIndex } = await helpersContract.getReserveData(weth.address); const { @@ -178,9 +178,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(true/*strategyWETH.stableBorrowRateEnabled*/); + expect(stableBorrowRateEnabled).to.be.equal(true /*strategyWETH.stableBorrowRateEnabled*/); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); - expect(variableBorrowIndex.toString()).to.be.equal(RAY); }); @@ -195,7 +194,9 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => { const { configurator, users, weth } = testEnv; await expect( - configurator.connect(users[2].signer).enableBorrowingOnReserve(weth.address, true), + configurator + .connect(users[2].signer) + .enableBorrowingOnReserve(weth.address, MAX_BORROW_CAP, true), CALLER_NOT_POOL_ADMIN ).to.be.revertedWith(CALLER_NOT_POOL_ADMIN); }); @@ -250,7 +251,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => { expect(ltv).to.be.equal(strategyWETH.baseLTVAsCollateral); expect(liquidationThreshold).to.be.equal(strategyWETH.liquidationThreshold); expect(liquidationBonus).to.be.equal(strategyWETH.liquidationBonus); - expect(stableBorrowRateEnabled).to.be.equal(true/*strategyWETH.stableBorrowRateEnabled*/); + expect(stableBorrowRateEnabled).to.be.equal(true /*strategyWETH.stableBorrowRateEnabled*/); expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor); }); diff --git a/test-suites/test-amm/helpers/make-suite.ts b/test-suites/test-amm/helpers/make-suite.ts index 71d96bf5..9ddbb7f1 100644 --- a/test-suites/test-amm/helpers/make-suite.ts +++ b/test-suites/test-amm/helpers/make-suite.ts @@ -15,7 +15,7 @@ import { getUniswapRepayAdapter, getFlashLiquidationAdapter, } from '../../../helpers/contracts-getters'; -import { eEthereumNetwork, tEthereumAddress } from '../../../helpers/types'; +import { eEthereumNetwork, eNetwork, tEthereumAddress } from '../../../helpers/types'; import { LendingPool } from '../../../types/LendingPool'; import { AaveProtocolDataProvider } from '../../../types/AaveProtocolDataProvider'; import { MintableERC20 } from '../../../types/MintableERC20'; @@ -116,9 +116,9 @@ export async function initializeMakeSuite() { testEnv.addressesProvider = await getLendingPoolAddressesProvider(); - if (process.env.MAINNET_FORK === 'true') { + if (process.env.FORK) { testEnv.registry = await getLendingPoolAddressesProviderRegistry( - getParamPerNetwork(AmmConfig.ProviderRegistry, eEthereumNetwork.main) + getParamPerNetwork(AmmConfig.ProviderRegistry, process.env.FORK as eNetwork) ); } else { testEnv.registry = await getLendingPoolAddressesProviderRegistry(); @@ -163,7 +163,7 @@ export async function initializeMakeSuite() { const setSnapshot = async () => { const hre = DRE as HardhatRuntimeEnvironment; if (usingTenderly()) { - setBuidlerevmSnapshotId((await hre.tenderlyRPC.getHead()) || '0x1'); + setBuidlerevmSnapshotId((await hre.tenderlyNetwork.getHead()) || '0x1'); return; } setBuidlerevmSnapshotId(await evmSnapshot()); @@ -172,7 +172,7 @@ const setSnapshot = async () => { const revertHead = async () => { const hre = DRE as HardhatRuntimeEnvironment; if (usingTenderly()) { - await hre.tenderlyRPC.setHead(buidlerevmSnapshotId); + await hre.tenderlyNetwork.setHead(buidlerevmSnapshotId); return; } await evmRevert(buidlerevmSnapshotId); diff --git a/test-suites/test-amm/pausable-functions.spec.ts b/test-suites/test-amm/pausable-functions.spec.ts index 2096b235..f42388a8 100644 --- a/test-suites/test-amm/pausable-functions.spec.ts +++ b/test-suites/test-amm/pausable-functions.spec.ts @@ -22,7 +22,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { _mockFlashLoanReceiver = await getMockFlashLoanReceiver(); }); - it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succees', async () => { + it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succeeds', async () => { const { users, pool, dai, aDai, configurator } = testEnv; const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000'); diff --git a/tsconfig.json b/tsconfig.json index 9974c3b6..44c4df6f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "noImplicitAny": false, "resolveJsonModule": true }, - "include": ["./scripts", "./test", "./tasks", "test-suites/test-aave/uniswapAdapters.repay.spec.ts", "test-suites/test-aave/upgradeability.spec.ts", "test-suites/test-aave/variable-debt-token.spec.ts", "test-suites/test-aave/weth-gateway.spec.ts"], + "include": ["./scripts", "./test", "./tasks", "./helpers", "test-suites/test-aave/uniswapAdapters.repay.spec.ts", "test-suites/test-aave/upgradeability.spec.ts", "test-suites/test-aave/variable-debt-token.spec.ts", "test-suites/test-aave/weth-gateway.spec.ts"], "files": [ "./hardhat.config.ts", "./modules/tenderly/tenderly.d.ts",