From 83bf3e567764883e2a91b79ff3b2b7e39be2a83c Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 15 Sep 2020 11:56:08 +0200 Subject: [PATCH] Trim PausablePool into LendingPool to save code size. --- contracts/lendingpool/LendingPool.sol | 65 +++++++++++++------ .../LendingPoolLiquidationManager.sol | 3 +- contracts/libraries/helpers/Errors.sol | 1 - contracts/misc/PausablePool.sol | 64 ------------------ test/pausable-functions.spec.ts | 40 ++++++------ 5 files changed, 68 insertions(+), 105 deletions(-) delete mode 100644 contracts/misc/PausablePool.sol diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 6808ecbc..7c259051 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -25,7 +25,6 @@ import {LendingPoolLiquidationManager} from './LendingPoolLiquidationManager.sol import {IPriceOracleGetter} from '../interfaces/IPriceOracleGetter.sol'; import {SafeERC20} from '@openzeppelin/contracts/token/ERC20/SafeERC20.sol'; import {ILendingPool} from '../interfaces/ILendingPool.sol'; -import {PausablePool} from '../misc/PausablePool.sol'; /** * @title LendingPool contract @@ -33,7 +32,7 @@ import {PausablePool} from '../misc/PausablePool.sol'; * @author Aave **/ -contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { +contract LendingPool is VersionedInitializable, ILendingPool { using SafeMath for uint256; using WadRayMath for uint256; using ReserveLogic for ReserveLogic.ReserveData; @@ -56,6 +55,7 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { address[] internal _reservesList; bool internal _flashLiquidationLocked; + bool public _paused; /** * @dev only lending pools configurator can use functions affected by this modifier @@ -68,6 +68,17 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { _; } + /** + * @dev Modifier to make a function callable only when the contract is not paused. + * + * Requirements: + * + * - The contract must not be paused. + */ + function whenNotPaused() internal view { + require(!_paused, Errors.IS_PAUSED); + } + uint256 public constant UINT_MAX_VALUE = uint256(-1); uint256 public constant LENDINGPOOL_REVISION = 0x2; @@ -97,7 +108,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { uint256 amount, address onBehalfOf, uint16 referralCode - ) external override whenNotPaused { + ) external override { + whenNotPaused(); ReserveLogic.ReserveData storage reserve = _reserves[asset]; ValidationLogic.validateDeposit(reserve, amount); @@ -125,7 +137,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { * @param asset the address of the reserve * @param amount the underlying amount to be redeemed **/ - function withdraw(address asset, uint256 amount) external override whenNotPaused { + function withdraw(address asset, uint256 amount) external override { + whenNotPaused(); ReserveLogic.ReserveData storage reserve = _reserves[asset]; address aToken = reserve.aTokenAddress; @@ -186,6 +199,7 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { uint256 interestRateMode, uint256 amount ) external override { + whenNotPaused(); address debtToken = _reserves[asset].getDebtTokenAddress(interestRateMode); _borrowAllowance[debtToken][msg.sender][user] = amount; @@ -207,7 +221,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { uint256 interestRateMode, uint16 referralCode, address onBehalfOf - ) external override whenNotPaused { + ) external override { + whenNotPaused(); ReserveLogic.ReserveData storage reserve = _reserves[asset]; if (onBehalfOf != msg.sender) { @@ -246,7 +261,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { uint256 amount, uint256 rateMode, address onBehalfOf - ) external override whenNotPaused { + ) external override { + whenNotPaused(); _executeRepay(asset, msg.sender, amount, rateMode, onBehalfOf); } @@ -307,7 +323,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { * @param asset the address of the reserve on which the user borrowed * @param rateMode the rate mode that the user wants to swap **/ - function swapBorrowRateMode(address asset, uint256 rateMode) external override whenNotPaused { + function swapBorrowRateMode(address asset, uint256 rateMode) external override { + whenNotPaused(); ReserveLogic.ReserveData storage reserve = _reserves[asset]; (uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve); @@ -350,7 +367,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { * @param asset the address of the reserve * @param user the address of the user to be rebalanced **/ - function rebalanceStableBorrowRate(address asset, address user) external override whenNotPaused { + function rebalanceStableBorrowRate(address asset, address user) external override { + whenNotPaused(); ReserveLogic.ReserveData storage reserve = _reserves[asset]; IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress); @@ -395,11 +413,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { * @param asset the address of the reserve * @param useAsCollateral true if the user wants to user the deposit as collateral, false otherwise. **/ - function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) - external - override - whenNotPaused - { + function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external override { + whenNotPaused(); ReserveLogic.ReserveData storage reserve = _reserves[asset]; ValidationLogic.validateSetUseReserveAsCollateral( @@ -435,7 +450,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { address user, uint256 purchaseAmount, bool receiveAToken - ) external override whenNotPaused { + ) external override { + whenNotPaused(); address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager(); //solium-disable-next-line @@ -491,7 +507,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { uint256 principalAmount, address receiver, bytes calldata params - ) external override whenNotPaused { + ) external override { + whenNotPaused(); require(!_flashLiquidationLocked, Errors.REENTRANCY_NOT_ALLOWED); _flashLiquidationLocked = true; @@ -538,7 +555,8 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { uint256 mode, bytes calldata params, uint16 referralCode - ) external override whenNotPaused { + ) external override { + whenNotPaused(); ReserveLogic.ReserveData storage reserve = _reserves[asset]; FlashLoanLocalVars memory vars; @@ -974,7 +992,7 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { address user, uint256 amount ) external override view returns (bool) { - if (PausablePool.paused()) { + if (_paused) { return false; } return @@ -1004,9 +1022,18 @@ contract LendingPool is VersionedInitializable, PausablePool, ILendingPool { } /** - * @dev pause or unpause all the Lending Pool actions and aToken transfers + * @dev Returns to normal state. + * + * Requirements: + * + * - The contract must be paused. */ function setPause(bool val) external override onlyLendingPoolConfigurator { - PausablePool._setPause(val); + _paused = val; + if (_paused) { + emit Paused(); + } else { + emit Unpaused(); + } } } diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol index cccca4fa..2520eb4b 100644 --- a/contracts/lendingpool/LendingPoolLiquidationManager.sol +++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol @@ -30,7 +30,7 @@ import {ValidationLogic} from '../libraries/logic/ValidationLogic.sol'; * @notice Implements the liquidation function. * @dev LendingPoolLiquidationManager inherits Pausable from OpenZeppelin to have the same storage layout as LendingPool **/ -contract LendingPoolLiquidationManager is VersionedInitializable, Pausable { +contract LendingPoolLiquidationManager is VersionedInitializable { using SafeERC20 for IERC20; using SafeMath for uint256; using WadRayMath for uint256; @@ -51,6 +51,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable, Pausable { address[] internal reservesList; bool internal _flashLiquidationLocked; + bool public _paused; uint256 internal constant LIQUIDATION_CLOSE_FACTOR_PERCENT = 5000; diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index 98dd62d4..0fd71e4c 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -79,7 +79,6 @@ library Errors { // pausable error message string public constant IS_PAUSED = '54'; // 'Pool is paused' - string public constant NOT_PAUSED = '55'; // 'Pool is not paused' enum LiquidationErrors { NO_ERROR, NO_COLLATERAL_AVAILABLE, diff --git a/contracts/misc/PausablePool.sol b/contracts/misc/PausablePool.sol deleted file mode 100644 index 092de7da..00000000 --- a/contracts/misc/PausablePool.sol +++ /dev/null @@ -1,64 +0,0 @@ -pragma solidity ^0.6.8; - -// Comments made with // are due current max code size at LendingPool - -// import {Errors} from '../libraries/helpers/Errors.sol'; - -/** - * @dev Contract module which allows children to implement an emergency stop - * mechanism that can be triggered by an authorized account. - * - * This module is used through inheritance. It will make available the - * modifiers `whenNotPaused` and `whenPaused`, which can be applied to - * the functions of your contract. Note that they will not be pausable by - * simply including this module, only once the modifiers are put in place. - */ -contract PausablePool { - /** - * @dev Emitted when the pause is triggered by `account`. - */ - event Paused(); - - /** - * @dev Emitted when the pause is lifted by `account`. - */ - event Unpaused(); - - bool private _paused; - - /** - * @dev Returns true if the contract is paused, and false otherwise. - */ - function paused() public virtual view returns (bool) { - return _paused; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - * - * Requirements: - * - * - The contract must not be paused. - */ - modifier whenNotPaused() { - // require(!_paused, Errors.IS_PAUSED); - require(!_paused, '54'); - _; - } - - /** - * @dev Returns to normal state. - * - * Requirements: - * - * - The contract must be paused. - */ - function _setPause(bool val) internal virtual { - _paused = val; - if (_paused) { - emit Paused(); - return; - } - emit Unpaused(); - } -} diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts index a9a460a3..bf6fc05e 100644 --- a/test/pausable-functions.spec.ts +++ b/test/pausable-functions.spec.ts @@ -40,7 +40,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { const user1Balance = await aDai.balanceOf(users[1].address); // Configurator pauses the pool - await configurator.pausePool(); + await configurator.setPoolPause(true); // User 0 tries the transfer to User 1 await expect( @@ -60,7 +60,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { ); // Configurator unpauses the pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); // User 0 succeeds transfer to User 1 await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit); @@ -89,13 +89,13 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); // Configurator pauses the pool - await configurator.pausePool(); + await configurator.setPoolPause(true); await expect( pool.connect(users[0].signer).deposit(dai.address, amountDAItoDeposit, users[0].address, '0') ).to.revertedWith(IS_PAUSED); // Configurator unpauses the pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); it('User 0 burns 1000 aDAI but reverts due pool is paused', async () => { @@ -112,7 +112,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { .deposit(dai.address, amountDAItoDeposit, users[0].address, '0'); // Configurator pauses the pool - await configurator.pausePool(); + await configurator.setPoolPause(true); // user tries to burn await expect( @@ -120,7 +120,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { ).to.revertedWith(IS_PAUSED); // Configurator unpauses the pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); it('Repay with collateral', async () => { @@ -129,7 +129,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { const liquidator = users[5]; // Pause the pool - await configurator.pausePool(); + await configurator.setPoolPause(true); // Try to execute liquidation await expect( @@ -146,7 +146,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { ).revertedWith(IS_PAUSED); // Unpause the pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); it('Flash loan', async () => { @@ -159,7 +159,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await _mockFlashLoanReceiver.setFailExecutionTransfer(true); // Pause pool - await configurator.pausePool(); + await configurator.setPoolPause(true); await expect( pool @@ -168,7 +168,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { ).revertedWith(IS_PAUSED); // Unpause pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); it('Liquidation call', async () => { @@ -238,7 +238,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { .toFixed(0); // Pause pool - await configurator.pausePool(); + await configurator.setPoolPause(true); // Do liquidation expect( @@ -246,7 +246,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { ).revertedWith(IS_PAUSED); // Unpause pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); it('User 6 deposits WETH and DAI, then borrows USDC at Variable', async () => { @@ -271,7 +271,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await mockSwapAdapter.setAmountToReturn(amountToRepay); // Pause pool - await configurator.pausePool(); + await configurator.setPoolPause(true); // Try to repay await expect( @@ -288,7 +288,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { ).revertedWith(IS_PAUSED); // Unpause pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); it('User 2 deposits WETH and DAI, then borrows USDC at Variable, then tries to swap to stable but pool is paused', async () => { @@ -309,7 +309,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); // Pause pool - await configurator.pausePool(); + await configurator.setPoolPause(true); // Try to repay await expect( @@ -317,21 +317,21 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { ).revertedWith(IS_PAUSED); // Unpause pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); it('User 2 tries to rebalance stable borrow rate', async () => { const {pool, dai, users, configurator} = testEnv; const user = users[1]; // Pause pool - await configurator.pausePool(); + await configurator.setPoolPause(true); await expect( pool.connect(user.signer).rebalanceStableBorrowRate(dai.address, user.address) ).revertedWith(IS_PAUSED); // Unpause pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); it('User 2 tries to rebalance stable borrow rate', async () => { @@ -344,13 +344,13 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { await pool.connect(user.signer).deposit(weth.address, amountWETHToDeposit, user.address, '0'); // Pause pool - await configurator.pausePool(); + await configurator.setPoolPause(true); await expect( pool.connect(user.signer).setUserUseReserveAsCollateral(weth.address, false) ).revertedWith(IS_PAUSED); // Unpause pool - await configurator.unpausePool(); + await configurator.setPoolPause(false); }); });