From 973f3f4fd9c76333128f92c9a48e3b228f0aac6c Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 00:29:00 +0200 Subject: [PATCH 01/11] feat: add pausability --- foundry.toml | 41 ++++++++++--------- .../static-a-token/DeprecationGap.sol | 10 +++++ .../static-a-token/StaticATokenLM.sol | 9 +++- 3 files changed, 39 insertions(+), 21 deletions(-) create mode 100644 src/periphery/contracts/static-a-token/DeprecationGap.sol diff --git a/foundry.toml b/foundry.toml index 61253e0b..0d5dd4c3 100644 --- a/foundry.toml +++ b/foundry.toml @@ -4,14 +4,17 @@ test = 'tests' script = 'scripts' optimizer = true optimizer_runs = 200 -solc='0.8.19' +solc = '0.8.20' evm_version = 'paris' bytecode_hash = 'none' out = 'out' libs = ['lib'] -remappings = [ +remappings = [] +fs_permissions = [ + { access = "write", path = "./reports" }, + { access = "read", path = "./out" }, + { access = "read", path = "./config" }, ] -fs_permissions = [{access = "write", path = "./reports"}, {access = "read", path = "./out" }, {access = "read", path = "./config"}] ffi = true [fuzz] @@ -25,7 +28,7 @@ avalanche = "${RPC_AVALANCHE}" polygon = "${RPC_POLYGON}" arbitrum = "${RPC_ARBITRUM}" fantom = "${RPC_FANTOM}" -scroll= "${RPC_SCROLL}" +scroll = "${RPC_SCROLL}" celo = "${RPC_CELO}" fantom_testnet = "${RPC_FANTOM_TESTNET}" harmony = "${RPC_HARMONY}" @@ -38,19 +41,19 @@ gnosis = "${RPC_GNOSIS}" base = "${RPC_BASE}" [etherscan] -mainnet={key="${ETHERSCAN_API_KEY_MAINNET}",chainId=1} -optimism={key="${ETHERSCAN_API_KEY_OPTIMISM}",chainId=10} -avalanche={key="${ETHERSCAN_API_KEY_AVALANCHE}",chainId=43114} -polygon={key="${ETHERSCAN_API_KEY_POLYGON}",chainId=137} -arbitrum={key="${ETHERSCAN_API_KEY_ARBITRUM}",chainId=42161} -fantom={key="${ETHERSCAN_API_KEY_FANTOM}",chainId=250} -scroll={key="${ETHERSCAN_API_KEY_SCROLL}",chainId=534352, url='https://api.scrollscan.com/api\?'} -celo={key="${ETHERSCAN_API_KEY_CELO}",chainId=42220} -sepolia={key="${ETHERSCAN_API_KEY_MAINNET}",chainId=11155111} -mumbai={key="${ETHERSCAN_API_KEY_POLYGON}",chainId=80001} -amoy={key="${ETHERSCAN_API_KEY_POLYGON}",chainId=80002} -bnb_testnet={key="${ETHERSCAN_API_KEY_BNB}",chainId=97,url='https://api-testnet.bscscan.com/api'} -bnb={key="${ETHERSCAN_API_KEY_BNB}",chainId=56,url='https://api.bscscan.com/api'} -base={key="${ETHERSCAN_API_KEY_BASE}",chain=8453} -gnosis={key="${ETHERSCAN_API_KEY_GNOSIS}",chainId=100} +mainnet = { key = "${ETHERSCAN_API_KEY_MAINNET}", chainId = 1 } +optimism = { key = "${ETHERSCAN_API_KEY_OPTIMISM}", chainId = 10 } +avalanche = { key = "${ETHERSCAN_API_KEY_AVALANCHE}", chainId = 43114 } +polygon = { key = "${ETHERSCAN_API_KEY_POLYGON}", chainId = 137 } +arbitrum = { key = "${ETHERSCAN_API_KEY_ARBITRUM}", chainId = 42161 } +fantom = { key = "${ETHERSCAN_API_KEY_FANTOM}", chainId = 250 } +scroll = { key = "${ETHERSCAN_API_KEY_SCROLL}", chainId = 534352, url = 'https://api.scrollscan.com/api\?' } +celo = { key = "${ETHERSCAN_API_KEY_CELO}", chainId = 42220 } +sepolia = { key = "${ETHERSCAN_API_KEY_MAINNET}", chainId = 11155111 } +mumbai = { key = "${ETHERSCAN_API_KEY_POLYGON}", chainId = 80001 } +amoy = { key = "${ETHERSCAN_API_KEY_POLYGON}", chainId = 80002 } +bnb_testnet = { key = "${ETHERSCAN_API_KEY_BNB}", chainId = 97, url = 'https://api-testnet.bscscan.com/api' } +bnb = { key = "${ETHERSCAN_API_KEY_BNB}", chainId = 56, url = 'https://api.bscscan.com/api' } +base = { key = "${ETHERSCAN_API_KEY_BASE}", chain = 8453 } +gnosis = { key = "${ETHERSCAN_API_KEY_GNOSIS}", chainId = 100 } # See more config options https://github.com/gakonst/foundry/tree/master/config diff --git a/src/periphery/contracts/static-a-token/DeprecationGap.sol b/src/periphery/contracts/static-a-token/DeprecationGap.sol new file mode 100644 index 00000000..803bfd89 --- /dev/null +++ b/src/periphery/contracts/static-a-token/DeprecationGap.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.10; + +/** + * This contract adds a single slot gap + * The slot is required to account for the now deprecated initializable + */ +contract DeprecationGap { + uint256 internal __gap; +} diff --git a/src/periphery/contracts/static-a-token/StaticATokenLM.sol b/src/periphery/contracts/static-a-token/StaticATokenLM.sol index 508d5a2e..4844a5e4 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenLM.sol @@ -21,6 +21,9 @@ import {IInitializableStaticATokenLM} from './interfaces/IInitializableStaticATo import {StaticATokenErrors} from './StaticATokenErrors.sol'; import {RayMathExplicitRounding, Rounding} from '../libraries/RayMathExplicitRounding.sol'; import {IERC4626} from './interfaces/IERC4626.sol'; +import {UpgradableOwnableWithGuardian} from 'solidity-utils/contracts/access-control/UpgradableOwnableWithGuardian.sol'; +import {PausableUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol'; +import {DeprecationGap} from './DeprecationGap.sol'; /** * @title StaticATokenLM @@ -30,10 +33,12 @@ import {IERC4626} from './interfaces/IERC4626.sol'; * @author BGD labs */ contract StaticATokenLM is - Initializable, + DeprecationGap, ERC20('STATIC__aToken_IMPL', 'STATIC__aToken_IMPL', 18), IStaticATokenLM, - Rescuable + Rescuable, + UpgradableOwnableWithGuardian, + PausableUpgradeable { using SafeERC20 for IERC20; using SafeCast for uint256; From 6e0ba31ab25b81cadabdd691f079b1d04e89aedb Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 00:46:34 +0200 Subject: [PATCH 02/11] fix: patch some docs --- .../static-a-token/StaticATokenLM.sol | 18 +++++++++++++++--- .../interfaces/IStaticATokenLM.sol | 7 +++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/periphery/contracts/static-a-token/StaticATokenLM.sol b/src/periphery/contracts/static-a-token/StaticATokenLM.sol index 4844a5e4..50815035 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenLM.sol @@ -22,8 +22,8 @@ import {StaticATokenErrors} from './StaticATokenErrors.sol'; import {RayMathExplicitRounding, Rounding} from '../libraries/RayMathExplicitRounding.sol'; import {IERC4626} from './interfaces/IERC4626.sol'; import {UpgradableOwnableWithGuardian} from 'solidity-utils/contracts/access-control/UpgradableOwnableWithGuardian.sol'; -import {PausableUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol'; import {DeprecationGap} from './DeprecationGap.sol'; +import {PausableUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol'; /** * @title StaticATokenLM @@ -66,6 +66,7 @@ contract StaticATokenLM is mapping(address => mapping(address => UserRewardsData)) internal _userRewardsData; constructor(IPool pool, IRewardsController rewardsController) { + _disableInitializers(); POOL = pool; INCENTIVES_CONTROLLER = rewardsController; } @@ -93,9 +94,20 @@ contract StaticATokenLM is emit Initialized(newAToken, staticATokenName, staticATokenSymbol); } + function initializeV2(address owner, address guardian) external reinitializer(2) { + __Ownable_init(owner); + __Ownable_With_Guardian_init(guardian); + } + /// @inheritdoc IRescuable function whoCanRescue() public view override returns (address) { - return POOL.ADDRESSES_PROVIDER().getACLAdmin(); + return owner(); + } + + ///@inheritdoc IStaticATokenLM + function setPaused(bool paused) external onlyOwnerOrGuardian { + if (paused) _pause(); + else _unpause(); } ///@inheritdoc IStaticATokenLM @@ -545,7 +557,7 @@ contract StaticATokenLM is * @param from The address of the sender of tokens * @param to The address of the receiver of tokens */ - function _beforeTokenTransfer(address from, address to, uint256) internal override { + function _beforeTokenTransfer(address from, address to, uint256) internal override whenNotPaused { for (uint256 i = 0; i < _rewardTokens.length; i++) { address rewardToken = address(_rewardTokens[i]); uint256 rewardsIndex = getCurrentRewardsIndex(rewardToken); diff --git a/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol b/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol index a5afeace..70830e96 100644 --- a/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol @@ -207,7 +207,14 @@ interface IStaticATokenLM is IInitializableStaticATokenLM, IERC4626 { /** * @notice Checks if the passed token is a registered reward. + * @param reward The reward to claim * @return bool signaling if token is a registered reward. */ function isRegisteredRewardToken(address reward) external view returns (bool); + + /** + * @notice Pauses the token which will forbid all transfers + * @param paused boolean determining if the token should be paused or unpaused + */ + function setPaused(bool paused) external; } From ccd099ea760ea85f75fe18bc574787a3aacb542d Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 08:50:52 +0200 Subject: [PATCH 03/11] fix: alter factory --- .../contracts/static-a-token/StaticATokenFactory.sol | 12 +++++++++--- .../contracts/static-a-token/StaticATokenLM.sol | 2 +- .../interfaces/IInitializableStaticATokenLM.sol | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/periphery/contracts/static-a-token/StaticATokenFactory.sol b/src/periphery/contracts/static-a-token/StaticATokenFactory.sol index c48e339a..0ae0bd84 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenFactory.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenFactory.sol @@ -4,6 +4,7 @@ pragma solidity ^0.8.10; import {IPool, DataTypes} from '../../../core/contracts/interfaces/IPool.sol'; import {IERC20Metadata} from 'solidity-utils/contracts/oz-common/interfaces/IERC20Metadata.sol'; import {ITransparentProxyFactory} from 'solidity-utils/contracts/transparent-proxy/interfaces/ITransparentProxyFactory.sol'; +import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {Initializable} from 'solidity-utils/contracts/transparent-proxy/Initializable.sol'; import {StaticATokenLM} from './StaticATokenLM.sol'; import {IStaticATokenFactory} from './interfaces/IStaticATokenFactory.sol'; @@ -17,7 +18,7 @@ import {IStaticATokenFactory} from './interfaces/IStaticATokenFactory.sol'; */ contract StaticATokenFactory is Initializable, IStaticATokenFactory { IPool public immutable POOL; - address public immutable ADMIN; + address public immutable PROXY_ADMIN; ITransparentProxyFactory public immutable TRANSPARENT_PROXY_FACTORY; address public immutable STATIC_A_TOKEN_IMPL; @@ -33,7 +34,7 @@ contract StaticATokenFactory is Initializable, IStaticATokenFactory { address staticATokenImpl ) { POOL = pool; - ADMIN = proxyAdmin; + PROXY_ADMIN = proxyAdmin; TRANSPARENT_PROXY_FACTORY = transparentProxyFactory; STATIC_A_TOKEN_IMPL = staticATokenImpl; } @@ -54,7 +55,7 @@ contract StaticATokenFactory is Initializable, IStaticATokenFactory { ); address staticAToken = TRANSPARENT_PROXY_FACTORY.createDeterministic( STATIC_A_TOKEN_IMPL, - ADMIN, + PROXY_ADMIN, abi.encodeWithSelector( StaticATokenLM.initialize.selector, reserveData.aTokenAddress, @@ -63,6 +64,11 @@ contract StaticATokenFactory is Initializable, IStaticATokenFactory { ), bytes32(uint256(uint160(underlyings[i]))) ); + StaticATokenLM(staticAToken).initializeRev2( + POOL.ADDRESSES_PROVIDER().getACLAdmin(), + address(0) // TODO: how to find guardian? + ); + _underlyingToStaticAToken[underlyings[i]] = staticAToken; staticATokens[i] = staticAToken; _staticATokens.push(staticAToken); diff --git a/src/periphery/contracts/static-a-token/StaticATokenLM.sol b/src/periphery/contracts/static-a-token/StaticATokenLM.sol index 50815035..fdbd213b 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenLM.sol @@ -94,7 +94,7 @@ contract StaticATokenLM is emit Initialized(newAToken, staticATokenName, staticATokenSymbol); } - function initializeV2(address owner, address guardian) external reinitializer(2) { + function initializeRev2(address owner, address guardian) external reinitializer(2) { __Ownable_init(owner); __Ownable_With_Guardian_init(guardian); } diff --git a/src/periphery/contracts/static-a-token/interfaces/IInitializableStaticATokenLM.sol b/src/periphery/contracts/static-a-token/interfaces/IInitializableStaticATokenLM.sol index 0eeb8955..0be9c301 100644 --- a/src/periphery/contracts/static-a-token/interfaces/IInitializableStaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/interfaces/IInitializableStaticATokenLM.sol @@ -29,4 +29,6 @@ interface IInitializableStaticATokenLM { string calldata staticATokenName, string calldata staticATokenSymbol ) external; + + function initializeRev2(address owner, address guardian) external; } From cecdaed3252faf692f2a80d79fcef640c69bb850 Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 08:59:56 +0200 Subject: [PATCH 04/11] test: add tests for rescuable --- .../static-a-token/StaticATokenLM.t.sol | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/periphery/static-a-token/StaticATokenLM.t.sol b/tests/periphery/static-a-token/StaticATokenLM.t.sol index 543a0c21..f899521b 100644 --- a/tests/periphery/static-a-token/StaticATokenLM.t.sol +++ b/tests/periphery/static-a-token/StaticATokenLM.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.10; +import {IRescuable} from 'solidity-utils/contracts/utils/Rescuable.sol'; import {AToken} from '../../../src/core/contracts/protocol/tokenization/AToken.sol'; import {DataTypes} from '../../../src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {IERC20, IERC20Metadata} from '../../../src/periphery/contracts/static-a-token/StaticATokenLM.sol'; @@ -556,6 +557,26 @@ contract StaticATokenLMTest is BaseTest { staticATokenLM.permit(permit.owner, permit.spender, permit.value, permit.deadline, v, r, s); } + function test_rescuable_shouldRevertForInvalidCaller() external { + deal(tokenList.usdx, address(staticATokenLM), 1 ether); + vm.expectRevert('ONLY_RESCUE_GUARDIAN'); + IRescuable(address(staticATokenLM)).emergencyTokenTransfer( + tokenList.usdx, + address(this), + 1 ether + ); + } + + function test_rescuable_shouldSuceedForOwner() external { + deal(tokenList.usdx, address(staticATokenLM), 1 ether); + vm.startPrank(poolAdmin); + IRescuable(address(staticATokenLM)).emergencyTokenTransfer( + tokenList.usdx, + address(this), + 1 ether + ); + } + function _configureLM() internal { PullRewardsTransferStrategy strat = new PullRewardsTransferStrategy( report.rewardsControllerProxy, From 9ee39d8df9db033a169af254a4fae0668a1fc55b Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 09:45:39 +0200 Subject: [PATCH 05/11] test: add pausability tests --- tests/periphery/static-a-token/Pausable.t.sol | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 tests/periphery/static-a-token/Pausable.t.sol diff --git a/tests/periphery/static-a-token/Pausable.t.sol b/tests/periphery/static-a-token/Pausable.t.sol new file mode 100644 index 00000000..4003ff79 --- /dev/null +++ b/tests/periphery/static-a-token/Pausable.t.sol @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.10; + +import {UpgradableOwnableWithGuardian} from 'solidity-utils/contracts/access-control/UpgradableOwnableWithGuardian.sol'; +import {PausableUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol'; +import {AToken} from '../../../src/core/contracts/protocol/tokenization/AToken.sol'; +import {DataTypes} from '../../../src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; +import {IERC20, IERC20Metadata} from '../../../src/periphery/contracts/static-a-token/StaticATokenLM.sol'; +import {RayMathExplicitRounding} from '../../../src/periphery/contracts/libraries/RayMathExplicitRounding.sol'; +import {PullRewardsTransferStrategy} from '../../../src/periphery/contracts/rewards/transfer-strategies/PullRewardsTransferStrategy.sol'; +import {RewardsDataTypes} from '../../../src/periphery/contracts/rewards/libraries/RewardsDataTypes.sol'; +import {ITransferStrategyBase} from '../../../src/periphery/contracts/rewards/interfaces/ITransferStrategyBase.sol'; +import {IEACAggregatorProxy} from '../../../src/periphery/contracts/misc/interfaces/IEACAggregatorProxy.sol'; +import {IStaticATokenLM} from '../../../src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol'; +import {SigUtils} from '../../utils/SigUtils.sol'; +import {BaseTest, TestnetERC20} from './TestBase.sol'; + +contract Pausable is BaseTest { + using RayMathExplicitRounding for uint256; + + function test_setPaused_shouldRevertForInvalidCaller(address actor) external { + vm.assume(actor != poolAdmin && actor != proxyAdmin); + vm.expectRevert( + abi.encodeWithSelector( + UpgradableOwnableWithGuardian.OnlyGuardianOrOwnerInvalidCaller.selector, + actor + ) + ); + _setPaused(actor, true); + } + + function test_setPaused_shouldSuceedForOwner() external { + assertEq(PausableUpgradeable(address(staticATokenLM)).paused(), false); + _setPaused(poolAdmin, true); + assertEq(PausableUpgradeable(address(staticATokenLM)).paused(), true); + } + + function test_deposit_shouldRevert() external { + vm.startPrank(user); + uint128 amountToDeposit = 5 ether; + _fundUser(amountToDeposit, user); + IERC20(UNDERLYING).approve(address(staticATokenLM), amountToDeposit); + vm.stopPrank(); + + _setPausedAsOwner(true); + vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); + vm.prank(user); + staticATokenLM.deposit(amountToDeposit, user, 0, true); + } + + function test_mint_shouldRevert() external { + vm.startPrank(user); + uint128 amountToDeposit = 5 ether; + _fundUser(amountToDeposit, user); + IERC20(UNDERLYING).approve(address(staticATokenLM), amountToDeposit); + vm.stopPrank(); + + uint256 sharesToMint = staticATokenLM.previewDeposit(amountToDeposit); + _setPausedAsOwner(true); + vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); + vm.prank(user); + staticATokenLM.mint(sharesToMint, user); + } + + function test_redeem_shouldRevert() external { + uint128 amountToDeposit = 5 ether; + vm.startPrank(user); + _fundUser(amountToDeposit, user); + _depositAToken(amountToDeposit, user); + vm.stopPrank(); + + assertEq(staticATokenLM.maxRedeem(user), staticATokenLM.balanceOf(user)); + + _setPausedAsOwner(true); + uint256 maxRedeem = staticATokenLM.maxRedeem(user); + vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); + vm.prank(user); + staticATokenLM.redeem(maxRedeem, user, user); + } + + function test_withdraw_shouldRevert() external { + uint128 amountToDeposit = 5 ether; + vm.startPrank(user); + _fundUser(amountToDeposit, user); + _depositAToken(amountToDeposit, user); + vm.stopPrank(); + + uint256 maxWithdraw = staticATokenLM.maxWithdraw(user); + _setPausedAsOwner(true); + vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); + vm.prank(user); + staticATokenLM.withdraw(maxWithdraw, user, user); + } + + function test_transfer_shouldRevert() external { + uint128 amountToDeposit = 10 ether; + vm.startPrank(user); + _fundUser(amountToDeposit, user); + _depositAToken(amountToDeposit, user); + vm.stopPrank(); + + _setPausedAsOwner(true); + vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); + vm.prank(user); + staticATokenLM.transfer(user1, amountToDeposit); + } + + function _setPausedAsOwner(bool paused) internal { + _setPaused(poolAdmin, paused); + } + + function _setPaused(address actor, bool paused) internal { + vm.prank(actor); + staticATokenLM.setPaused(paused); + } +} From 7ddae5da2ff54b2714df1f570017f4e4a5be24c5 Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 13:31:53 +0200 Subject: [PATCH 06/11] fix: update contracts --- .../static-a-token/DeprecationGap.sol | 6 +++-- .../static-a-token/StaticATokenFactory.sol | 4 --- .../static-a-token/StaticATokenLM.sol | 27 ++++++++++--------- .../IInitializableStaticATokenLM.sol | 2 -- .../interfaces/IStaticATokenLM.sol | 2 ++ tests/periphery/static-a-token/Pausable.t.sol | 14 +++++----- .../static-a-token/StaticATokenLM.t.sol | 5 ++-- 7 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/periphery/contracts/static-a-token/DeprecationGap.sol b/src/periphery/contracts/static-a-token/DeprecationGap.sol index 803bfd89..c3b4b47b 100644 --- a/src/periphery/contracts/static-a-token/DeprecationGap.sol +++ b/src/periphery/contracts/static-a-token/DeprecationGap.sol @@ -3,8 +3,10 @@ pragma solidity ^0.8.10; /** * This contract adds a single slot gap - * The slot is required to account for the now deprecated initializable + * The slot is required to account for the now deprecated Initializable. + * The new version of Initializable uses erc7201, so it no longer occupies the first slot. + * https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/contracts/proxy/utils/Initializable.sol#L60 */ contract DeprecationGap { - uint256 internal __gap; + uint256 internal __deprecated_initializable_gap; } diff --git a/src/periphery/contracts/static-a-token/StaticATokenFactory.sol b/src/periphery/contracts/static-a-token/StaticATokenFactory.sol index 0ae0bd84..4ea0534c 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenFactory.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenFactory.sol @@ -64,10 +64,6 @@ contract StaticATokenFactory is Initializable, IStaticATokenFactory { ), bytes32(uint256(uint160(underlyings[i]))) ); - StaticATokenLM(staticAToken).initializeRev2( - POOL.ADDRESSES_PROVIDER().getACLAdmin(), - address(0) // TODO: how to find guardian? - ); _underlyingToStaticAToken[underlyings[i]] = staticAToken; staticATokens[i] = staticAToken; diff --git a/src/periphery/contracts/static-a-token/StaticATokenLM.sol b/src/periphery/contracts/static-a-token/StaticATokenLM.sol index fdbd213b..0057b932 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenLM.sol @@ -1,13 +1,13 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.10; +import {IPool} from '../../../core/contracts/interfaces/IPool.sol'; import {IPool} from '../../../core/contracts/interfaces/IPool.sol'; import {DataTypes, ReserveConfiguration} from '../../../core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {IRewardsController} from '../rewards/interfaces/IRewardsController.sol'; import {WadRayMath} from '../../../core/contracts/protocol/libraries/math/WadRayMath.sol'; import {MathUtils} from '../../../core/contracts/protocol/libraries/math/MathUtils.sol'; import {SafeCast} from 'solidity-utils/contracts/oz-common/SafeCast.sol'; -import {Initializable} from 'solidity-utils/contracts/transparent-proxy/Initializable.sol'; import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol'; import {IERC20Metadata} from 'solidity-utils/contracts/oz-common/interfaces/IERC20Metadata.sol'; import {IERC20} from 'solidity-utils/contracts/oz-common/interfaces/IERC20.sol'; @@ -21,9 +21,9 @@ import {IInitializableStaticATokenLM} from './interfaces/IInitializableStaticATo import {StaticATokenErrors} from './StaticATokenErrors.sol'; import {RayMathExplicitRounding, Rounding} from '../libraries/RayMathExplicitRounding.sol'; import {IERC4626} from './interfaces/IERC4626.sol'; -import {UpgradableOwnableWithGuardian} from 'solidity-utils/contracts/access-control/UpgradableOwnableWithGuardian.sol'; -import {DeprecationGap} from './DeprecationGap.sol'; import {PausableUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol'; +import {DeprecationGap} from './DeprecationGap.sol'; +import {IACLManager} from '../../../core/contracts/interfaces/IACLManager.sol'; /** * @title StaticATokenLM @@ -37,7 +37,6 @@ contract StaticATokenLM is ERC20('STATIC__aToken_IMPL', 'STATIC__aToken_IMPL', 18), IStaticATokenLM, Rescuable, - UpgradableOwnableWithGuardian, PausableUpgradeable { using SafeERC20 for IERC20; @@ -66,11 +65,20 @@ contract StaticATokenLM is mapping(address => mapping(address => UserRewardsData)) internal _userRewardsData; constructor(IPool pool, IRewardsController rewardsController) { - _disableInitializers(); + _disableInitializers(); POOL = pool; INCENTIVES_CONTROLLER = rewardsController; } + modifier onlyPauseGuardian() { + if(!canPause(msg.sender)) revert OnlyPauseGuardian(msg.sender); + _; + } + + function canPause(address actor) public returns(bool) { + return IACLManager(POOL.ADDRESSES_PROVIDER().getACLManager()).isEmergencyAdmin(actor); + } + ///@inheritdoc IInitializableStaticATokenLM function initialize( address newAToken, @@ -94,18 +102,13 @@ contract StaticATokenLM is emit Initialized(newAToken, staticATokenName, staticATokenSymbol); } - function initializeRev2(address owner, address guardian) external reinitializer(2) { - __Ownable_init(owner); - __Ownable_With_Guardian_init(guardian); - } - /// @inheritdoc IRescuable function whoCanRescue() public view override returns (address) { - return owner(); + return POOL.ADDRESSES_PROVIDER().getACLAdmin(); } ///@inheritdoc IStaticATokenLM - function setPaused(bool paused) external onlyOwnerOrGuardian { + function setPaused(bool paused) external onlyPauseGuardian { if (paused) _pause(); else _unpause(); } diff --git a/src/periphery/contracts/static-a-token/interfaces/IInitializableStaticATokenLM.sol b/src/periphery/contracts/static-a-token/interfaces/IInitializableStaticATokenLM.sol index 0be9c301..0eeb8955 100644 --- a/src/periphery/contracts/static-a-token/interfaces/IInitializableStaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/interfaces/IInitializableStaticATokenLM.sol @@ -29,6 +29,4 @@ interface IInitializableStaticATokenLM { string calldata staticATokenName, string calldata staticATokenSymbol ) external; - - function initializeRev2(address owner, address guardian) external; } diff --git a/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol b/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol index 70830e96..535ada58 100644 --- a/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol @@ -30,6 +30,8 @@ interface IStaticATokenLM is IInitializableStaticATokenLM, IERC4626 { uint248 lastUpdatedIndex; } + error OnlyPauseGuardian(address caller); + event RewardTokenRegistered(address indexed reward, uint256 startIndex); /** diff --git a/tests/periphery/static-a-token/Pausable.t.sol b/tests/periphery/static-a-token/Pausable.t.sol index 4003ff79..afb90ca2 100644 --- a/tests/periphery/static-a-token/Pausable.t.sol +++ b/tests/periphery/static-a-token/Pausable.t.sol @@ -22,7 +22,7 @@ contract Pausable is BaseTest { vm.assume(actor != poolAdmin && actor != proxyAdmin); vm.expectRevert( abi.encodeWithSelector( - UpgradableOwnableWithGuardian.OnlyGuardianOrOwnerInvalidCaller.selector, + IStaticATokenLM.OnlyPauseGuardian.selector, actor ) ); @@ -42,7 +42,7 @@ contract Pausable is BaseTest { IERC20(UNDERLYING).approve(address(staticATokenLM), amountToDeposit); vm.stopPrank(); - _setPausedAsOwner(true); + _setPausedAsAclAdmin(true); vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); vm.prank(user); staticATokenLM.deposit(amountToDeposit, user, 0, true); @@ -56,7 +56,7 @@ contract Pausable is BaseTest { vm.stopPrank(); uint256 sharesToMint = staticATokenLM.previewDeposit(amountToDeposit); - _setPausedAsOwner(true); + _setPausedAsAclAdmin(true); vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); vm.prank(user); staticATokenLM.mint(sharesToMint, user); @@ -71,7 +71,7 @@ contract Pausable is BaseTest { assertEq(staticATokenLM.maxRedeem(user), staticATokenLM.balanceOf(user)); - _setPausedAsOwner(true); + _setPausedAsAclAdmin(true); uint256 maxRedeem = staticATokenLM.maxRedeem(user); vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); vm.prank(user); @@ -86,7 +86,7 @@ contract Pausable is BaseTest { vm.stopPrank(); uint256 maxWithdraw = staticATokenLM.maxWithdraw(user); - _setPausedAsOwner(true); + _setPausedAsAclAdmin(true); vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); vm.prank(user); staticATokenLM.withdraw(maxWithdraw, user, user); @@ -99,13 +99,13 @@ contract Pausable is BaseTest { _depositAToken(amountToDeposit, user); vm.stopPrank(); - _setPausedAsOwner(true); + _setPausedAsAclAdmin(true); vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); vm.prank(user); staticATokenLM.transfer(user1, amountToDeposit); } - function _setPausedAsOwner(bool paused) internal { + function _setPausedAsAclAdmin(bool paused) internal { _setPaused(poolAdmin, paused); } diff --git a/tests/periphery/static-a-token/StaticATokenLM.t.sol b/tests/periphery/static-a-token/StaticATokenLM.t.sol index f899521b..81f8f495 100644 --- a/tests/periphery/static-a-token/StaticATokenLM.t.sol +++ b/tests/periphery/static-a-token/StaticATokenLM.t.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.10; import {IRescuable} from 'solidity-utils/contracts/utils/Rescuable.sol'; +import {Initializable} from 'openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol'; import {AToken} from '../../../src/core/contracts/protocol/tokenization/AToken.sol'; import {DataTypes} from '../../../src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {IERC20, IERC20Metadata} from '../../../src/periphery/contracts/static-a-token/StaticATokenLM.sol'; @@ -30,8 +31,8 @@ contract StaticATokenLMTest is BaseTest { function test_initializeShouldRevert() public { address impl = factory.STATIC_A_TOKEN_IMPL(); - vm.expectRevert(); - IStaticATokenLM(impl).initialize(0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8, 'hey', 'ho'); + vm.expectRevert(Initializable.InvalidInitialization.selector); + IStaticATokenLM(impl).initialize(A_TOKEN, 'hey', 'ho'); } function test_getters() public view { From 361c1d9de7638f37d8e8881515375bca6fb1e966 Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 13:34:59 +0200 Subject: [PATCH 07/11] fix: minor cleanup --- .../contracts/static-a-token/StaticATokenFactory.sol | 1 - src/periphery/contracts/static-a-token/StaticATokenLM.sol | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/periphery/contracts/static-a-token/StaticATokenFactory.sol b/src/periphery/contracts/static-a-token/StaticATokenFactory.sol index 4ea0534c..4e0f8bd0 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenFactory.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenFactory.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.10; import {IPool, DataTypes} from '../../../core/contracts/interfaces/IPool.sol'; import {IERC20Metadata} from 'solidity-utils/contracts/oz-common/interfaces/IERC20Metadata.sol'; import {ITransparentProxyFactory} from 'solidity-utils/contracts/transparent-proxy/interfaces/ITransparentProxyFactory.sol'; -import {ProxyAdmin} from 'solidity-utils/contracts/transparent-proxy/ProxyAdmin.sol'; import {Initializable} from 'solidity-utils/contracts/transparent-proxy/Initializable.sol'; import {StaticATokenLM} from './StaticATokenLM.sol'; import {IStaticATokenFactory} from './interfaces/IStaticATokenFactory.sol'; diff --git a/src/periphery/contracts/static-a-token/StaticATokenLM.sol b/src/periphery/contracts/static-a-token/StaticATokenLM.sol index 0057b932..fb717f4a 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenLM.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.10; -import {IPool} from '../../../core/contracts/interfaces/IPool.sol'; import {IPool} from '../../../core/contracts/interfaces/IPool.sol'; import {DataTypes, ReserveConfiguration} from '../../../core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; -import {IRewardsController} from '../rewards/interfaces/IRewardsController.sol'; import {WadRayMath} from '../../../core/contracts/protocol/libraries/math/WadRayMath.sol'; import {MathUtils} from '../../../core/contracts/protocol/libraries/math/MathUtils.sol'; +import {IACLManager} from '../../../core/contracts/interfaces/IACLManager.sol'; +import {IRewardsController} from '../rewards/interfaces/IRewardsController.sol'; import {SafeCast} from 'solidity-utils/contracts/oz-common/SafeCast.sol'; import {SafeERC20} from 'solidity-utils/contracts/oz-common/SafeERC20.sol'; import {IERC20Metadata} from 'solidity-utils/contracts/oz-common/interfaces/IERC20Metadata.sol'; @@ -23,7 +23,6 @@ import {RayMathExplicitRounding, Rounding} from '../libraries/RayMathExplicitRou import {IERC4626} from './interfaces/IERC4626.sol'; import {PausableUpgradeable} from 'openzeppelin-contracts-upgradeable/contracts/utils/PausableUpgradeable.sol'; import {DeprecationGap} from './DeprecationGap.sol'; -import {IACLManager} from '../../../core/contracts/interfaces/IACLManager.sol'; /** * @title StaticATokenLM From 3d5fa0e84e8cd3d99b17452ffcdbdfe0b6a52eed Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 8 Aug 2024 14:51:33 +0200 Subject: [PATCH 08/11] Update src/periphery/contracts/static-a-token/StaticATokenLM.sol Co-authored-by: Ernesto Boado --- src/periphery/contracts/static-a-token/StaticATokenLM.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/periphery/contracts/static-a-token/StaticATokenLM.sol b/src/periphery/contracts/static-a-token/StaticATokenLM.sol index fb717f4a..da2f3608 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenLM.sol @@ -74,7 +74,7 @@ contract StaticATokenLM is _; } - function canPause(address actor) public returns(bool) { + function canPause(address actor) public view returns(bool) { return IACLManager(POOL.ADDRESSES_PROVIDER().getACLManager()).isEmergencyAdmin(actor); } From 7ec0a0f41f93e2d366b877c2b60653f8c8638e49 Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 15:00:20 +0200 Subject: [PATCH 09/11] ifx: add test for claiming rewards --- .../static-a-token/StaticATokenLM.sol | 2 +- tests/periphery/static-a-token/Pausable.t.sol | 14 ++++++ .../static-a-token/StaticATokenLM.t.sol | 43 ------------------ tests/periphery/static-a-token/TestBase.sol | 44 +++++++++++++++++++ 4 files changed, 59 insertions(+), 44 deletions(-) diff --git a/src/periphery/contracts/static-a-token/StaticATokenLM.sol b/src/periphery/contracts/static-a-token/StaticATokenLM.sol index da2f3608..e6884511 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenLM.sol @@ -652,7 +652,7 @@ contract StaticATokenLM is address onBehalfOf, address receiver, address[] memory rewards - ) internal { + ) internal whenNotPaused { for (uint256 i = 0; i < rewards.length; i++) { if (address(rewards[i]) == address(0)) { continue; diff --git a/tests/periphery/static-a-token/Pausable.t.sol b/tests/periphery/static-a-token/Pausable.t.sol index afb90ca2..4c7b2a64 100644 --- a/tests/periphery/static-a-token/Pausable.t.sol +++ b/tests/periphery/static-a-token/Pausable.t.sol @@ -105,6 +105,20 @@ contract Pausable is BaseTest { staticATokenLM.transfer(user1, amountToDeposit); } + function test_claimingRewards_shouldRevert() external { + _configureLM(); + uint128 amountToDeposit = 10 ether; + vm.startPrank(user); + _fundUser(amountToDeposit, user); + _depositAToken(amountToDeposit, user); + vm.stopPrank(); + + _setPausedAsAclAdmin(true); + vm.expectRevert(PausableUpgradeable.EnforcedPause.selector); + vm.prank(user); + staticATokenLM.claimRewardsToSelf(rewardTokens); + } + function _setPausedAsAclAdmin(bool paused) internal { _setPaused(poolAdmin, paused); } diff --git a/tests/periphery/static-a-token/StaticATokenLM.t.sol b/tests/periphery/static-a-token/StaticATokenLM.t.sol index 81f8f495..9b2b2fe3 100644 --- a/tests/periphery/static-a-token/StaticATokenLM.t.sol +++ b/tests/periphery/static-a-token/StaticATokenLM.t.sol @@ -7,10 +7,6 @@ import {AToken} from '../../../src/core/contracts/protocol/tokenization/AToken.s import {DataTypes} from '../../../src/core/contracts/protocol/libraries/configuration/ReserveConfiguration.sol'; import {IERC20, IERC20Metadata} from '../../../src/periphery/contracts/static-a-token/StaticATokenLM.sol'; import {RayMathExplicitRounding} from '../../../src/periphery/contracts/libraries/RayMathExplicitRounding.sol'; -import {PullRewardsTransferStrategy} from '../../../src/periphery/contracts/rewards/transfer-strategies/PullRewardsTransferStrategy.sol'; -import {RewardsDataTypes} from '../../../src/periphery/contracts/rewards/libraries/RewardsDataTypes.sol'; -import {ITransferStrategyBase} from '../../../src/periphery/contracts/rewards/interfaces/ITransferStrategyBase.sol'; -import {IEACAggregatorProxy} from '../../../src/periphery/contracts/misc/interfaces/IEACAggregatorProxy.sol'; import {IStaticATokenLM} from '../../../src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol'; import {SigUtils} from '../../utils/SigUtils.sol'; import {BaseTest, TestnetERC20} from './TestBase.sol'; @@ -18,8 +14,6 @@ import {BaseTest, TestnetERC20} from './TestBase.sol'; contract StaticATokenLMTest is BaseTest { using RayMathExplicitRounding for uint256; - address public constant EMISSION_ADMIN = address(25); - function setUp() public override { super.setUp(); @@ -578,43 +572,6 @@ contract StaticATokenLMTest is BaseTest { ); } - function _configureLM() internal { - PullRewardsTransferStrategy strat = new PullRewardsTransferStrategy( - report.rewardsControllerProxy, - EMISSION_ADMIN, - EMISSION_ADMIN - ); - - vm.startPrank(poolAdmin); - contracts.emissionManager.setEmissionAdmin(REWARD_TOKEN, EMISSION_ADMIN); - vm.stopPrank(); - - vm.startPrank(EMISSION_ADMIN); - IERC20(REWARD_TOKEN).approve(address(strat), 10_000 ether); - vm.stopPrank(); - - vm.startPrank(OWNER); - TestnetERC20(REWARD_TOKEN).mint(EMISSION_ADMIN, 10_000 ether); - vm.stopPrank(); - - RewardsDataTypes.RewardsConfigInput[] memory config = new RewardsDataTypes.RewardsConfigInput[]( - 1 - ); - config[0] = RewardsDataTypes.RewardsConfigInput( - 0.00385 ether, - 10_000 ether, - uint32(block.timestamp + 30 days), - A_TOKEN, - REWARD_TOKEN, - ITransferStrategyBase(strat), - IEACAggregatorProxy(address(2)) - ); - - vm.prank(EMISSION_ADMIN); - contracts.emissionManager.configureAssets(config); - - staticATokenLM.refreshRewardTokens(); - } function _openSupplyAndBorrowPositions() internal { // this is to open borrow positions so that the aToken balance increases diff --git a/tests/periphery/static-a-token/TestBase.sol b/tests/periphery/static-a-token/TestBase.sol index 058ad713..e421c858 100644 --- a/tests/periphery/static-a-token/TestBase.sol +++ b/tests/periphery/static-a-token/TestBase.sol @@ -2,6 +2,10 @@ pragma solidity ^0.8.10; import {IRewardsController} from '../../../src/periphery/contracts/rewards/interfaces/IRewardsController.sol'; +import {RewardsDataTypes} from '../../../src/periphery/contracts/rewards/libraries/RewardsDataTypes.sol'; +import {PullRewardsTransferStrategy} from '../../../src/periphery/contracts/rewards/transfer-strategies/PullRewardsTransferStrategy.sol'; +import {ITransferStrategyBase} from '../../../src/periphery/contracts/rewards/interfaces/ITransferStrategyBase.sol'; +import {IEACAggregatorProxy} from '../../../src/periphery/contracts/misc/interfaces/IEACAggregatorProxy.sol'; import {TransparentUpgradeableProxy} from 'solidity-utils/contracts/transparent-proxy/TransparentUpgradeableProxy.sol'; import {ITransparentProxyFactory} from 'solidity-utils/contracts/transparent-proxy/TransparentProxyFactory.sol'; import {IPool} from '../../../src/core/contracts/interfaces/IPool.sol'; @@ -13,6 +17,7 @@ import {DataTypes} from '../../../src/core/contracts/protocol/libraries/configur abstract contract BaseTest is TestnetProcedures { address constant OWNER = address(1234); + address public constant EMISSION_ADMIN = address(25); address public user; address public user1; @@ -61,6 +66,45 @@ abstract contract BaseTest is TestnetProcedures { staticATokenLM = StaticATokenLM(factory.getStaticAToken(UNDERLYING)); } + + function _configureLM() internal { + PullRewardsTransferStrategy strat = new PullRewardsTransferStrategy( + report.rewardsControllerProxy, + EMISSION_ADMIN, + EMISSION_ADMIN + ); + + vm.startPrank(poolAdmin); + contracts.emissionManager.setEmissionAdmin(REWARD_TOKEN, EMISSION_ADMIN); + vm.stopPrank(); + + vm.startPrank(EMISSION_ADMIN); + IERC20(REWARD_TOKEN).approve(address(strat), 10_000 ether); + vm.stopPrank(); + + vm.startPrank(OWNER); + TestnetERC20(REWARD_TOKEN).mint(EMISSION_ADMIN, 10_000 ether); + vm.stopPrank(); + + RewardsDataTypes.RewardsConfigInput[] memory config = new RewardsDataTypes.RewardsConfigInput[]( + 1 + ); + config[0] = RewardsDataTypes.RewardsConfigInput( + 0.00385 ether, + 10_000 ether, + uint32(block.timestamp + 30 days), + A_TOKEN, + REWARD_TOKEN, + ITransferStrategyBase(strat), + IEACAggregatorProxy(address(2)) + ); + + vm.prank(EMISSION_ADMIN); + contracts.emissionManager.configureAssets(config); + + staticATokenLM.refreshRewardTokens(); + } + function _fundUser(uint128 amountToDeposit, address targetUser) internal { deal(UNDERLYING, targetUser, amountToDeposit); } From caede7b8aa5b14e4646f21878b00ba94d6b6646b Mon Sep 17 00:00:00 2001 From: sakulstra Date: Thu, 8 Aug 2024 15:12:47 +0200 Subject: [PATCH 10/11] fix: lint --- .../static-a-token/StaticATokenLM.sol | 8 +- tests/periphery/static-a-token/Pausable.t.sol | 9 +-- .../static-a-token/StaticATokenLM.t.sol | 1 - tests/periphery/static-a-token/TestBase.sol | 73 +++++++++---------- 4 files changed, 42 insertions(+), 49 deletions(-) diff --git a/src/periphery/contracts/static-a-token/StaticATokenLM.sol b/src/periphery/contracts/static-a-token/StaticATokenLM.sol index e6884511..5ca0fb29 100644 --- a/src/periphery/contracts/static-a-token/StaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/StaticATokenLM.sol @@ -64,18 +64,18 @@ contract StaticATokenLM is mapping(address => mapping(address => UserRewardsData)) internal _userRewardsData; constructor(IPool pool, IRewardsController rewardsController) { - _disableInitializers(); + _disableInitializers(); POOL = pool; INCENTIVES_CONTROLLER = rewardsController; } modifier onlyPauseGuardian() { - if(!canPause(msg.sender)) revert OnlyPauseGuardian(msg.sender); + if (!canPause(msg.sender)) revert OnlyPauseGuardian(msg.sender); _; } - function canPause(address actor) public view returns(bool) { - return IACLManager(POOL.ADDRESSES_PROVIDER().getACLManager()).isEmergencyAdmin(actor); + function canPause(address actor) public view returns (bool) { + return IACLManager(POOL.ADDRESSES_PROVIDER().getACLManager()).isEmergencyAdmin(actor); } ///@inheritdoc IInitializableStaticATokenLM diff --git a/tests/periphery/static-a-token/Pausable.t.sol b/tests/periphery/static-a-token/Pausable.t.sol index 4c7b2a64..966a33ac 100644 --- a/tests/periphery/static-a-token/Pausable.t.sol +++ b/tests/periphery/static-a-token/Pausable.t.sol @@ -20,12 +20,7 @@ contract Pausable is BaseTest { function test_setPaused_shouldRevertForInvalidCaller(address actor) external { vm.assume(actor != poolAdmin && actor != proxyAdmin); - vm.expectRevert( - abi.encodeWithSelector( - IStaticATokenLM.OnlyPauseGuardian.selector, - actor - ) - ); + vm.expectRevert(abi.encodeWithSelector(IStaticATokenLM.OnlyPauseGuardian.selector, actor)); _setPaused(actor, true); } @@ -106,7 +101,7 @@ contract Pausable is BaseTest { } function test_claimingRewards_shouldRevert() external { - _configureLM(); + _configureLM(); uint128 amountToDeposit = 10 ether; vm.startPrank(user); _fundUser(amountToDeposit, user); diff --git a/tests/periphery/static-a-token/StaticATokenLM.t.sol b/tests/periphery/static-a-token/StaticATokenLM.t.sol index 9b2b2fe3..6f2ddaf4 100644 --- a/tests/periphery/static-a-token/StaticATokenLM.t.sol +++ b/tests/periphery/static-a-token/StaticATokenLM.t.sol @@ -572,7 +572,6 @@ contract StaticATokenLMTest is BaseTest { ); } - function _openSupplyAndBorrowPositions() internal { // this is to open borrow positions so that the aToken balance increases address whale = address(79); diff --git a/tests/periphery/static-a-token/TestBase.sol b/tests/periphery/static-a-token/TestBase.sol index e421c858..b20aab9c 100644 --- a/tests/periphery/static-a-token/TestBase.sol +++ b/tests/periphery/static-a-token/TestBase.sol @@ -66,44 +66,43 @@ abstract contract BaseTest is TestnetProcedures { staticATokenLM = StaticATokenLM(factory.getStaticAToken(UNDERLYING)); } - function _configureLM() internal { - PullRewardsTransferStrategy strat = new PullRewardsTransferStrategy( - report.rewardsControllerProxy, - EMISSION_ADMIN, - EMISSION_ADMIN - ); - - vm.startPrank(poolAdmin); - contracts.emissionManager.setEmissionAdmin(REWARD_TOKEN, EMISSION_ADMIN); - vm.stopPrank(); - - vm.startPrank(EMISSION_ADMIN); - IERC20(REWARD_TOKEN).approve(address(strat), 10_000 ether); - vm.stopPrank(); - - vm.startPrank(OWNER); - TestnetERC20(REWARD_TOKEN).mint(EMISSION_ADMIN, 10_000 ether); - vm.stopPrank(); - - RewardsDataTypes.RewardsConfigInput[] memory config = new RewardsDataTypes.RewardsConfigInput[]( - 1 - ); - config[0] = RewardsDataTypes.RewardsConfigInput( - 0.00385 ether, - 10_000 ether, - uint32(block.timestamp + 30 days), - A_TOKEN, - REWARD_TOKEN, - ITransferStrategyBase(strat), - IEACAggregatorProxy(address(2)) - ); - - vm.prank(EMISSION_ADMIN); - contracts.emissionManager.configureAssets(config); - - staticATokenLM.refreshRewardTokens(); - } + PullRewardsTransferStrategy strat = new PullRewardsTransferStrategy( + report.rewardsControllerProxy, + EMISSION_ADMIN, + EMISSION_ADMIN + ); + + vm.startPrank(poolAdmin); + contracts.emissionManager.setEmissionAdmin(REWARD_TOKEN, EMISSION_ADMIN); + vm.stopPrank(); + + vm.startPrank(EMISSION_ADMIN); + IERC20(REWARD_TOKEN).approve(address(strat), 10_000 ether); + vm.stopPrank(); + + vm.startPrank(OWNER); + TestnetERC20(REWARD_TOKEN).mint(EMISSION_ADMIN, 10_000 ether); + vm.stopPrank(); + + RewardsDataTypes.RewardsConfigInput[] memory config = new RewardsDataTypes.RewardsConfigInput[]( + 1 + ); + config[0] = RewardsDataTypes.RewardsConfigInput( + 0.00385 ether, + 10_000 ether, + uint32(block.timestamp + 30 days), + A_TOKEN, + REWARD_TOKEN, + ITransferStrategyBase(strat), + IEACAggregatorProxy(address(2)) + ); + + vm.prank(EMISSION_ADMIN); + contracts.emissionManager.configureAssets(config); + + staticATokenLM.refreshRewardTokens(); + } function _fundUser(uint128 amountToDeposit, address targetUser) internal { deal(UNDERLYING, targetUser, amountToDeposit); From a4491933bac4368b33dc59b672d16c3fc005551f Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 8 Aug 2024 15:18:27 +0200 Subject: [PATCH 11/11] Update src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol Co-authored-by: Ernesto Boado --- .../contracts/static-a-token/interfaces/IStaticATokenLM.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol b/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol index 535ada58..18edaeb7 100644 --- a/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol +++ b/src/periphery/contracts/static-a-token/interfaces/IStaticATokenLM.sol @@ -215,7 +215,7 @@ interface IStaticATokenLM is IInitializableStaticATokenLM, IERC4626 { function isRegisteredRewardToken(address reward) external view returns (bool); /** - * @notice Pauses the token which will forbid all transfers + * @notice Pauses/unpauses all system's operations * @param paused boolean determining if the token should be paused or unpaused */ function setPaused(bool paused) external;