mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge pull request #108 from aave/feat/2.5-pause-one-reserve
Feat/2.5 pause one reserve
This commit is contained in:
commit
bfc0602736
|
@ -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
|
||||
|
@ -221,7 +233,11 @@ interface ILendingPoolConfigurator {
|
|||
* @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;
|
||||
function enableBorrowingOnReserve(
|
||||
address asset,
|
||||
uint256 borrowCap,
|
||||
bool stableBorrowRateEnabled
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @dev Disables borrowing on a reserve
|
||||
|
@ -282,6 +298,18 @@ interface ILendingPoolConfigurator {
|
|||
**/
|
||||
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
|
||||
|
|
|
@ -64,7 +64,7 @@ contract AaveProtocolDataProvider {
|
|||
return aTokens;
|
||||
}
|
||||
|
||||
// not returning borrow and supply caps for compatibility
|
||||
// not returning borrow and supply caps for compatibility, nor pause flag
|
||||
function getReserveConfigurationData(address asset)
|
||||
external
|
||||
view
|
||||
|
@ -87,7 +87,7 @@ contract AaveProtocolDataProvider {
|
|||
(ltv, liquidationThreshold, liquidationBonus, decimals, reserveFactor) =
|
||||
configuration.getParamsMemory();
|
||||
|
||||
(isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled) =
|
||||
(isActive, isFrozen, borrowingEnabled, stableBorrowRateEnabled, ) =
|
||||
configuration.getFlagsMemory();
|
||||
|
||||
usageAsCollateralEnabled = liquidationThreshold > 0;
|
||||
|
@ -103,6 +103,13 @@ contract AaveProtocolDataProvider {
|
|||
.getCapsMemory();
|
||||
}
|
||||
|
||||
function getPaused(address asset) external view returns (bool isPaused) {
|
||||
(, , , , isPaused) =
|
||||
ILendingPool(ADDRESSES_PROVIDER.getLendingPool())
|
||||
.getConfiguration(asset)
|
||||
.getFlagsMemory();
|
||||
}
|
||||
|
||||
function getReserveData(address asset)
|
||||
external
|
||||
view
|
||||
|
|
|
@ -122,7 +122,8 @@ contract UiPoolDataProvider is IUiPoolDataProvider {
|
|||
reserveData.isActive,
|
||||
reserveData.isFrozen,
|
||||
reserveData.borrowingEnabled,
|
||||
reserveData.stableBorrowRateEnabled
|
||||
reserveData.stableBorrowRateEnabled,
|
||||
reserveData.isPaused
|
||||
) = baseData.configuration.getFlagsMemory();
|
||||
reserveData.usageAsCollateralEnabled = reserveData.baseLTVasCollateral != 0;
|
||||
(
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,6 +22,7 @@ interface IUiPoolDataProvider {
|
|||
bool stableBorrowRateEnabled;
|
||||
bool isActive;
|
||||
bool isFrozen;
|
||||
bool isPaused;
|
||||
// base data
|
||||
uint128 liquidityIndex;
|
||||
uint128 variableBorrowIndex;
|
||||
|
|
|
@ -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);
|
||||
|
@ -720,6 +720,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) {
|
||||
|
|
|
@ -46,6 +46,15 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
|
|||
_;
|
||||
}
|
||||
|
||||
modifier onlyEmergencyOrPoolAdmin {
|
||||
require(
|
||||
_addressesProvider.getEmergencyAdmin() == msg.sender ||
|
||||
_addressesProvider.getPoolAdmin() == msg.sender,
|
||||
Errors.LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
uint256 internal constant CONFIGURATOR_REVISION = 0x1;
|
||||
|
||||
function getRevision() internal pure override returns (uint256) {
|
||||
|
@ -126,6 +135,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);
|
||||
|
@ -380,6 +390,28 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
|
|||
emit ReserveUnfrozen(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 onlyPoolAdmin {
|
||||
DataTypes.ReserveConfigurationMap memory currentConfig = _pool.getConfiguration(asset);
|
||||
|
|
|
@ -18,6 +18,7 @@ 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
|
||||
|
@ -30,6 +31,8 @@ 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;
|
||||
|
@ -187,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
|
||||
|
@ -336,6 +359,7 @@ library ReserveConfiguration {
|
|||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool
|
||||
)
|
||||
{
|
||||
|
@ -345,7 +369,8 @@ 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
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -447,6 +472,7 @@ library ReserveConfiguration {
|
|||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool
|
||||
)
|
||||
{
|
||||
|
@ -454,7 +480,8 @@ 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
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -106,6 +106,8 @@ library Errors {
|
|||
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';
|
||||
|
||||
enum CollateralManagerErrors {
|
||||
NO_ERROR,
|
||||
|
@ -117,6 +119,7 @@ library Errors {
|
|||
NO_ACTIVE_RESERVE,
|
||||
HEALTH_FACTOR_LOWER_THAN_LIQUIDATION_THRESHOLD,
|
||||
INVALID_EQUAL_ASSETS_TO_SWAP,
|
||||
FROZEN_RESERVE
|
||||
FROZEN_RESERVE,
|
||||
PAUSED_RESERVE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,12 +42,13 @@ library ValidationLogic {
|
|||
*/
|
||||
function validateDeposit(DataTypes.ReserveData storage reserve, uint256 amount) internal view {
|
||||
DataTypes.ReserveConfigurationMap memory reserveConfiguration = reserve.configuration;
|
||||
(bool isActive, bool isFrozen, , ) = reserveConfiguration.getFlagsMemory();
|
||||
(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 ||
|
||||
|
@ -71,8 +72,9 @@ library ValidationLogic {
|
|||
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 {
|
||||
|
@ -89,6 +91,7 @@ library ValidationLogic {
|
|||
uint256 borrowCap;
|
||||
bool isActive;
|
||||
bool isFrozen;
|
||||
bool isPaused;
|
||||
bool borrowingEnabled;
|
||||
bool stableRateBorrowingEnabled;
|
||||
}
|
||||
|
@ -121,7 +124,7 @@ library ValidationLogic {
|
|||
mapping(uint256 => address) storage reserves,
|
||||
uint256 reservesCount,
|
||||
address oracle
|
||||
) internal view {
|
||||
) external view {
|
||||
ValidateBorrowLocalVars memory vars;
|
||||
|
||||
DataTypes.ReserveConfigurationMap memory reserveConfiguration = reserve.configuration;
|
||||
|
@ -131,10 +134,12 @@ library ValidationLogic {
|
|||
vars.isActive,
|
||||
vars.isFrozen,
|
||||
vars.borrowingEnabled,
|
||||
vars.stableRateBorrowingEnabled
|
||||
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);
|
||||
|
||||
|
@ -238,9 +243,9 @@ library ValidationLogic {
|
|||
uint256 stableDebt,
|
||||
uint256 variableDebt
|
||||
) external view {
|
||||
bool isActive = reserve.configuration.getActive();
|
||||
|
||||
(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);
|
||||
|
||||
|
@ -273,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) {
|
||||
|
@ -317,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 =
|
||||
|
@ -348,6 +356,9 @@ library ValidationLogic {
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
@ -357,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) external 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);
|
||||
}
|
||||
|
||||
|
@ -386,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 (
|
||||
|
@ -448,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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,8 @@ 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
|
||||
|
|
|
@ -181,6 +181,8 @@ export enum ProtocolErrors {
|
|||
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',
|
||||
|
||||
// old
|
||||
|
||||
|
|
|
@ -92,6 +92,8 @@ export const strategyMATIC: IReserveParams = {
|
|||
borrowCap: '0',
|
||||
supplyCap: '0',
|
||||
reserveFactor: '2000',
|
||||
borrowCap: '0',
|
||||
supplyCap: '0',
|
||||
};
|
||||
|
||||
export const strategyAAVE: IReserveParams = {
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
"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 --skip-registry",
|
||||
|
|
|
@ -23,6 +23,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
RC_INVALID_RESERVE_FACTOR,
|
||||
RC_INVALID_BORROW_CAP,
|
||||
RC_INVALID_SUPPLY_CAP,
|
||||
LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN,
|
||||
VL_RESERVE_PAUSED,
|
||||
} = ProtocolErrors;
|
||||
|
||||
it('Reverts trying to set an invalid reserve factor', async () => {
|
||||
|
@ -65,6 +67,152 @@ 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()
|
||||
);
|
||||
|
||||
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 } = testEnv;
|
||||
expect(users[1].address).to.be.equal(await addressesProvider.getEmergencyAdmin());
|
||||
|
||||
await configurator.connect(users[1].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 } = testEnv;
|
||||
await configurator.connect(users[1].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 } = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].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 } = testEnv;
|
||||
await expect(
|
||||
configurator.connect(users[2].signer).unpauseReserve(weth.address),
|
||||
CALLER_NOT_POOL_ADMIN
|
||||
).to.be.revertedWith(LPC_CALLER_NOT_EMERGENCY_OR_POOL_ADMIN);
|
||||
});
|
||||
|
||||
it('Freezes the ETH reserve', async () => {
|
||||
const { configurator, weth, helpersContract } = testEnv;
|
||||
|
@ -82,9 +230,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -112,9 +262,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -157,9 +309,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -188,9 +342,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -236,9 +392,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -266,9 +424,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -305,9 +465,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -334,9 +496,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -402,9 +566,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -446,9 +612,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
@ -475,9 +643,11 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
|
|||
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);
|
||||
|
|
|
@ -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');
|
||||
|
|
330
test-suites/test-aave/reserve-pause.spec.ts
Normal file
330
test-suites/test-aave/reserve-pause.spec.ts
Normal file
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
|
|
Loading…
Reference in New Issue
Block a user