Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds the ability to freeze individual reserves to the emergency admin #296

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions contracts/protocol/lendingpool/LendingPoolConfigurator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
_;
}

modifier onlyPoolOrEmergencyAdmin {
require(
addressesProvider.getPoolAdmin() == msg.sender || addressesProvider.getEmergencyAdmin() == msg.sender,
Errors.LPC_NOT_POOL_OR_EMERGENCY_ADMIN
);
_;
}

uint256 internal constant CONFIGURATOR_REVISION = 0x1;

function getRevision() internal pure override returns (uint256) {
Expand Down Expand Up @@ -391,7 +399,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
* 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 {
function freezeReserve(address asset) external onlyPoolOrEmergencyAdmin {
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

currentConfig.setFrozen(true);
Expand All @@ -405,7 +413,7 @@ contract LendingPoolConfigurator is VersionedInitializable, ILendingPoolConfigur
* @dev Unfreezes a reserve
* @param asset The address of the underlying asset of the reserve
**/
function unfreezeReserve(address asset) external onlyPoolAdmin {
function unfreezeReserve(address asset) external onlyPoolOrEmergencyAdmin {
DataTypes.ReserveConfigurationMap memory currentConfig = pool.getConfiguration(asset);

currentConfig.setFrozen(false);
Expand Down
1 change: 1 addition & 0 deletions contracts/protocol/libraries/helpers/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ 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 LPC_NOT_POOL_OR_EMERGENCY_ADMIN = '81';

enum CollateralManagerErrors {
NO_ERROR,
Expand Down
1 change: 1 addition & 0 deletions helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ export enum ProtocolErrors {
RC_INVALID_DECIMALS = '70',
RC_INVALID_RESERVE_FACTOR = '71',
LPAPR_INVALID_ADDRESSES_PROVIDER_ID = '72',
LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN = '81',

// old

Expand Down
71 changes: 63 additions & 8 deletions test-suites/test-aave/configurator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
RC_INVALID_LIQ_BONUS,
RC_INVALID_DECIMALS,
RC_INVALID_RESERVE_FACTOR,
LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN
} = ProtocolErrors;

it('Reverts trying to set an invalid reserve factor', async () => {
Expand Down Expand Up @@ -58,7 +59,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
});

it('Freezes the ETH reserve', async () => {
it('Freezes the ETH reserve using the pool admin', async () => {
const { configurator, weth, helpersContract } = testEnv;

await configurator.freezeReserve(weth.address);
Expand All @@ -85,7 +86,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});

it('Unfreezes the ETH reserve', async () => {
it('Unfreezes the ETH reserve using the pool admin', async () => {
const { configurator, helpersContract, weth } = testEnv;
await configurator.unfreezeReserve(weth.address);

Expand All @@ -112,20 +113,74 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});

it('Check the onlyAaveAdmin on freezeReserve ', async () => {
it('Freezes the ETH reserve using the emergency admin', async () => {
const { configurator, weth, helpersContract, users } = testEnv;

await configurator.connect(users[1].signer).freezeReserve(weth.address);
const {
decimals,
ltv,
liquidationBonus,
liquidationThreshold,
reserveFactor,
stableBorrowRateEnabled,
borrowingEnabled,
isActive,
isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address);

expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
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);
});

it('Unfreezes the ETH reserve using the emergency admin', async () => {
const { configurator, helpersContract, weth, users } = testEnv;
await configurator.connect(users[1].signer).unfreezeReserve(weth.address);

const {
decimals,
ltv,
liquidationBonus,
liquidationThreshold,
reserveFactor,
stableBorrowRateEnabled,
borrowingEnabled,
isActive,
isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address);

expect(borrowingEnabled).to.be.equal(true);
expect(isActive).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);
});

it('Check the onlyPoolOrEmergencyAdmin on freezeReserve ', async () => {
const { configurator, users, weth } = testEnv;
await expect(
configurator.connect(users[2].signer).freezeReserve(weth.address),
CALLER_NOT_POOL_ADMIN
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN
).to.be.revertedWith(LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN);
});

it('Check the onlyAaveAdmin on unfreezeReserve ', async () => {
it('Check the onlyPoolOrEmergencyAdmin on unfreezeReserve ', async () => {
const { configurator, users, weth } = testEnv;
await expect(
configurator.connect(users[2].signer).unfreezeReserve(weth.address),
CALLER_NOT_POOL_ADMIN
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN
).to.be.revertedWith(LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN);
});

it('Deactivates the ETH reserve for borrowing', async () => {
Expand Down
76 changes: 66 additions & 10 deletions test-suites/test-amm/configurator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
RC_INVALID_LIQ_BONUS,
RC_INVALID_DECIMALS,
RC_INVALID_RESERVE_FACTOR,
LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN
} = ProtocolErrors;

it('Reverts trying to set an invalid reserve factor', async () => {
Expand Down Expand Up @@ -58,7 +59,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
});

it('Freezes the ETH reserve', async () => {
it('Freezes the ETH reserve using the pool admin', async () => {
const { configurator, weth, helpersContract } = testEnv;

await configurator.freezeReserve(weth.address);
Expand All @@ -85,7 +86,7 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});

it('Unfreezes the ETH reserve', async () => {
it('Unfreezes the ETH reserve using the pool admin', async () => {
const { configurator, helpersContract, weth } = testEnv;
await configurator.unfreezeReserve(weth.address);

Expand All @@ -112,20 +113,75 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
expect(reserveFactor).to.be.equal(strategyWETH.reserveFactor);
});

it('Check the onlyAaveAdmin on freezeReserve ', async () => {
it('Freezes the ETH reserve using the emergency admin', async () => {
const { configurator, weth, helpersContract, users } = testEnv;

await configurator.connect(users[1].signer).freezeReserve(weth.address);
const {
decimals,
ltv,
liquidationBonus,
liquidationThreshold,
reserveFactor,
stableBorrowRateEnabled,
borrowingEnabled,
isActive,
isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address);

expect(borrowingEnabled).to.be.equal(true);
expect(isActive).to.be.equal(true);
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);
});

it('Unfreezes the ETH reserve using the emergency admin', async () => {
const { configurator, helpersContract, weth, users } = testEnv;
await configurator.connect(users[1].signer).unfreezeReserve(weth.address);

const {
decimals,
ltv,
liquidationBonus,
liquidationThreshold,
reserveFactor,
stableBorrowRateEnabled,
borrowingEnabled,
isActive,
isFrozen,
} = await helpersContract.getReserveConfigurationData(weth.address);

expect(borrowingEnabled).to.be.equal(true);
expect(isActive).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);
});


it('Check the onlyPoolOrEmergencyAdmin on freezeReserve ', async () => {
const { configurator, users, weth } = testEnv;
await expect(
configurator.connect(users[2].signer).freezeReserve(weth.address),
CALLER_NOT_POOL_ADMIN
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN
).to.be.revertedWith(LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN);
});

it('Check the onlyAaveAdmin on unfreezeReserve ', async () => {
it('Check the onlyPoolOrEmergencyAdmin on unfreezeReserve ', async () => {
const { configurator, users, weth } = testEnv;
await expect(
configurator.connect(users[2].signer).unfreezeReserve(weth.address),
CALLER_NOT_POOL_ADMIN
).to.be.revertedWith(CALLER_NOT_POOL_ADMIN);
LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN
).to.be.revertedWith(LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN);
});

it('Deactivates the ETH reserve for borrowing', async () => {
Expand Down Expand Up @@ -188,8 +244,8 @@ makeSuite('LendingPoolConfigurator', (testEnv: TestEnv) => {
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);
LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN
).to.be.revertedWith(LPC_CALLER_NOT_POOL_OR_EMERGENCY_ADMIN);
});

it('Check the onlyAaveAdmin on enableBorrowingOnReserve ', async () => {
Expand Down