From bdc4ed8072280902d3a6440d6ed526e9aa8f239f Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Thu, 11 Apr 2024 18:41:40 -0400 Subject: [PATCH] account multicall --- justfile | 6 +- script/DeployLlamaAccountMulticall.s.sol | 70 ++++++++++++++ script/DeployLlamaRewardsClaimer.s.sol | 70 -------------- ...g.json => mockAccountMulticallConfig.json} | 2 +- ...onfig.json => accountMulticallConfig.json} | 2 +- .../LlamaAccountMulticallExtension.sol} | 26 ++--- .../LlamaAccountMulticallGuard.sol} | 23 ++--- .../LlamaAccountMulticallStorage.sol} | 8 +- .../LlamaAccountMulticallExtension.t.sol} | 41 ++++---- .../LlamaAccountMulticallGuard.t.sol | 96 +++++++++++++++++++ .../LlamaAccountMulticallStorage.t.sol | 56 +++++++++++ .../LlamaAccountMulticallTestSetup.sol} | 70 +++++++------- .../LlamaRewardsClaimGuard.t.sol | 96 ------------------- .../LlamaRewardsClaimStorage.t.sol | 54 ----------- 14 files changed, 309 insertions(+), 311 deletions(-) create mode 100644 script/DeployLlamaAccountMulticall.s.sol delete mode 100644 script/DeployLlamaRewardsClaimer.s.sol rename script/input/1/{mockRewardsClaimerConfig.json => mockAccountMulticallConfig.json} (78%) rename script/input/11155111/{rewardsClaimerConfig.json => accountMulticallConfig.json} (77%) rename src/{rewards-claimer/LlamaRewardsClaimAccountExtension.sol => account-multicall/LlamaAccountMulticallExtension.sol} (62%) rename src/{rewards-claimer/LlamaRewardsClaimGuard.sol => account-multicall/LlamaAccountMulticallGuard.sol} (57%) rename src/{rewards-claimer/LlamaRewardsClaimStorage.sol => account-multicall/LlamaAccountMulticallStorage.sol} (89%) rename test/{rewards-claimer/LlamaRewardsClaimAccountExtension.t.sol => account-multicall/LlamaAccountMulticallExtension.t.sol} (74%) create mode 100644 test/account-multicall/LlamaAccountMulticallGuard.t.sol create mode 100644 test/account-multicall/LlamaAccountMulticallStorage.t.sol rename test/{rewards-claimer/LlamaRewardsClaimTestSetup.sol => account-multicall/LlamaAccountMulticallTestSetup.sol} (65%) delete mode 100644 test/rewards-claimer/LlamaRewardsClaimGuard.t.sol delete mode 100644 test/rewards-claimer/LlamaRewardsClaimStorage.t.sol diff --git a/justfile b/justfile index 9787e0c..f68eb32 100644 --- a/justfile +++ b/justfile @@ -28,10 +28,10 @@ dry-run-deploy-voting-module: (run-deploy-voting-module-script '') deploy-voting-module: (run-deploy-voting-module-script '--broadcast --verify') -run-deploy-rewards-claimer-script flags: (run-script 'DeployLlamaRewardsClaimer' flags '--sig "run(string)"' '"rewardsClaimerConfig.json"') +run-deploy-account-multicall-script flags: (run-script 'DeployLlamaAccountMulticall' flags '--sig "run(string)"' '"accountMulticallConfig.json"') -dry-run-deploy-rewards-claimer: (run-deploy-rewards-claimer-script '') +dry-run-deploy-account-multicall: (run-deploy-account-multicall-script '') -deploy-rewards-claimer: (run-deploy-rewards-claimer-script '--broadcast --verify --slow') +deploy-account-multicall: (run-deploy-account-multicall-script '--broadcast --verify --slow') verify: (run-script 'DeployLlamaTokenVotingFactory' '--verify --resume') diff --git a/script/DeployLlamaAccountMulticall.s.sol b/script/DeployLlamaAccountMulticall.s.sol new file mode 100644 index 0000000..a8499a5 --- /dev/null +++ b/script/DeployLlamaAccountMulticall.s.sol @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.23; + +import {Script, stdJson} from "forge-std/Script.sol"; + +import {DeployUtils} from "script/DeployUtils.sol"; + +import {LlamaAccountMulticallExtension} from "src/account-multicall/LlamaAccountMulticallExtension.sol"; +import {LlamaAccountMulticallGuard} from "src/account-multicall/LlamaAccountMulticallGuard.sol"; +import {LlamaAccountMulticallStorage} from "src/account-multicall/LlamaAccountMulticallStorage.sol"; + +contract DeployLlamaAccountMulticall is Script { + using stdJson for string; + + struct TargetSelectorAuthorizationInputs { + // Attributes need to be in alphabetical order so JSON decodes properly. + string comment; + bytes selector; + address target; + } + + // Account multicall contracts. + LlamaAccountMulticallStorage accountMulticallStorage; + LlamaAccountMulticallExtension accountMulticallExtension; + LlamaAccountMulticallGuard accountMulticallGuard; + + function run(string memory configFile) public { + string memory jsonInput = DeployUtils.readScriptInput(configFile); + + address llamaExecutor = jsonInput.readAddress(".llamaExecutor"); + LlamaAccountMulticallStorage.TargetSelectorAuthorization[] memory data = readTargetSelectorAuthorizations(jsonInput); + + DeployUtils.print(string.concat("Deploying Llama rewards claimer contracts to chain:", vm.toString(block.chainid))); + + vm.broadcast(); + accountMulticallStorage = new LlamaAccountMulticallStorage(llamaExecutor, data); + DeployUtils.print(string.concat(" LlamaAccountMulticallStorage: ", vm.toString(address(accountMulticallStorage)))); + + vm.broadcast(); + accountMulticallExtension = new LlamaAccountMulticallExtension(accountMulticallStorage); + DeployUtils.print( + string.concat(" LlamaAccountMulticallExtension: ", vm.toString(address(accountMulticallExtension))) + ); + + vm.broadcast(); + accountMulticallGuard = new LlamaAccountMulticallGuard(accountMulticallExtension); + DeployUtils.print(string.concat(" LlamaAccountMulticallGuard: ", vm.toString(address(accountMulticallGuard)))); + } + + function readTargetSelectorAuthorizations(string memory jsonInput) + internal + pure + returns (LlamaAccountMulticallStorage.TargetSelectorAuthorization[] memory) + { + bytes memory data = jsonInput.parseRaw(".initialTargetSelectorAuthorizations"); + + TargetSelectorAuthorizationInputs[] memory rawConfigs = abi.decode(data, (TargetSelectorAuthorizationInputs[])); + + LlamaAccountMulticallStorage.TargetSelectorAuthorization[] memory configs = + new LlamaAccountMulticallStorage.TargetSelectorAuthorization[](rawConfigs.length); + + for (uint256 i = 0; i < rawConfigs.length; i++) { + configs[i].target = rawConfigs[i].target; + configs[i].selector = bytes4(rawConfigs[i].selector); + configs[i].isAuthorized = true; + } + + return configs; + } +} diff --git a/script/DeployLlamaRewardsClaimer.s.sol b/script/DeployLlamaRewardsClaimer.s.sol deleted file mode 100644 index d3ea264..0000000 --- a/script/DeployLlamaRewardsClaimer.s.sol +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.23; - -import {Script, stdJson} from "forge-std/Script.sol"; - -import {DeployUtils} from "script/DeployUtils.sol"; - -import {LlamaRewardsClaimAccountExtension} from "src/rewards-claimer/LlamaRewardsClaimAccountExtension.sol"; -import {LlamaRewardsClaimGuard} from "src/rewards-claimer/LlamaRewardsClaimGuard.sol"; -import {LlamaRewardsClaimStorage} from "src/rewards-claimer/LlamaRewardsClaimStorage.sol"; - -contract DeployLlamaRewardsClaimer is Script { - using stdJson for string; - - struct TargetSelectorAuthorizationInputs { - // Attributes need to be in alphabetical order so JSON decodes properly. - string comment; - bytes selector; - address target; - } - - // Rewards claim contracts. - LlamaRewardsClaimStorage rewardsClaimStorage; - LlamaRewardsClaimAccountExtension rewardsClaimAccountExtension; - LlamaRewardsClaimGuard rewardsClaimGuard; - - function run(string memory configFile) public { - string memory jsonInput = DeployUtils.readScriptInput(configFile); - - address llamaExecutor = jsonInput.readAddress(".llamaExecutor"); - LlamaRewardsClaimStorage.TargetSelectorAuthorization[] memory data = readTargetSelectorAuthorizations(jsonInput); - - DeployUtils.print(string.concat("Deploying Llama rewards claimer contracts to chain:", vm.toString(block.chainid))); - - vm.broadcast(); - rewardsClaimStorage = new LlamaRewardsClaimStorage(llamaExecutor, data); - DeployUtils.print(string.concat(" LlamaRewardsClaimStorage: ", vm.toString(address(rewardsClaimStorage)))); - - vm.broadcast(); - rewardsClaimAccountExtension = new LlamaRewardsClaimAccountExtension(rewardsClaimStorage); - DeployUtils.print( - string.concat(" LlamaRewardsClaimAccountExtension: ", vm.toString(address(rewardsClaimAccountExtension))) - ); - - vm.broadcast(); - rewardsClaimGuard = new LlamaRewardsClaimGuard(rewardsClaimAccountExtension); - DeployUtils.print(string.concat(" LlamaRewardsClaimGuard: ", vm.toString(address(rewardsClaimGuard)))); - } - - function readTargetSelectorAuthorizations(string memory jsonInput) - internal - pure - returns (LlamaRewardsClaimStorage.TargetSelectorAuthorization[] memory) - { - bytes memory data = jsonInput.parseRaw(".initialTargetSelectorAuthorizations"); - - TargetSelectorAuthorizationInputs[] memory rawConfigs = abi.decode(data, (TargetSelectorAuthorizationInputs[])); - - LlamaRewardsClaimStorage.TargetSelectorAuthorization[] memory configs = - new LlamaRewardsClaimStorage.TargetSelectorAuthorization[](rawConfigs.length); - - for (uint256 i = 0; i < rawConfigs.length; i++) { - configs[i].target = rawConfigs[i].target; - configs[i].selector = bytes4(rawConfigs[i].selector); - configs[i].isAuthorized = true; - } - - return configs; - } -} diff --git a/script/input/1/mockRewardsClaimerConfig.json b/script/input/1/mockAccountMulticallConfig.json similarity index 78% rename from script/input/1/mockRewardsClaimerConfig.json rename to script/input/1/mockAccountMulticallConfig.json index 3510945..89d934e 100644 --- a/script/input/1/mockRewardsClaimerConfig.json +++ b/script/input/1/mockAccountMulticallConfig.json @@ -1,5 +1,5 @@ { - "comment": "This is a rewards claimer deployment for Forge tests.", + "comment": "This is an account multicall deployment for Forge tests.", "llamaExecutor": "0xdAf00E9786cABB195a8a1Cf102730863aE94Dd75", "initialTargetSelectorAuthorizations": [ { diff --git a/script/input/11155111/rewardsClaimerConfig.json b/script/input/11155111/accountMulticallConfig.json similarity index 77% rename from script/input/11155111/rewardsClaimerConfig.json rename to script/input/11155111/accountMulticallConfig.json index 90efb70..c02bfcc 100644 --- a/script/input/11155111/rewardsClaimerConfig.json +++ b/script/input/11155111/accountMulticallConfig.json @@ -1,5 +1,5 @@ { - "comment": "This is an example rewards claimer deployment on Sepolia.", + "comment": "This is an example account multicall deployment on Sepolia.", "llamaExecutor": "0x0000000000000000000000000000000000000000", "initialTargetSelectorAuthorizations": [ { diff --git a/src/rewards-claimer/LlamaRewardsClaimAccountExtension.sol b/src/account-multicall/LlamaAccountMulticallExtension.sol similarity index 62% rename from src/rewards-claimer/LlamaRewardsClaimAccountExtension.sol rename to src/account-multicall/LlamaAccountMulticallExtension.sol index e767c3d..350095c 100644 --- a/src/rewards-claimer/LlamaRewardsClaimAccountExtension.sol +++ b/src/account-multicall/LlamaAccountMulticallExtension.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.23; +import {LlamaAccountMulticallStorage} from "src/account-multicall/LlamaAccountMulticallStorage.sol"; import {LlamaBaseAccountExtension} from "src/common/LlamaBaseAccountExtension.sol"; import {LlamaUtils} from "src/lib/LlamaUtils.sol"; -import {LlamaRewardsClaimStorage} from "src/rewards-claimer/LlamaRewardsClaimStorage.sol"; -/// @title Llama Rewards Claim Account Extension +/// @title Llama Account Multicall Extension /// @author Llama (devsdosomething@llama.xyz) -/// @notice An account extension that claims rewards on behalf of the Llama account. +/// @notice An account extension that can multicall on behalf of the Llama account. /// @dev This contract should be delegate-called from a Llama account. -contract LlamaRewardsClaimAccountExtension is LlamaBaseAccountExtension { +contract LlamaAccountMulticallExtension is LlamaBaseAccountExtension { /// @dev Struct to hold target data. struct TargetData { address target; // The target contract. @@ -25,18 +25,18 @@ contract LlamaRewardsClaimAccountExtension is LlamaBaseAccountExtension { /// @dev Thrown if the target-selector is not authorized. error UnauthorizedTargetSelector(address target, bytes4 selector); - /// @notice The rewards claim storage contract. - LlamaRewardsClaimStorage public immutable REWARDS_CLAIM_STORAGE; + /// @notice The Llama account multicall storage contract. + LlamaAccountMulticallStorage public immutable ACCOUNT_MULTICALL_STORAGE; - /// @dev Initializes the Llama rewards claim account extenstion. - constructor(LlamaRewardsClaimStorage rewardsClaimStorage) { - REWARDS_CLAIM_STORAGE = rewardsClaimStorage; + /// @dev Initializes the Llama account multicall extenstion. + constructor(LlamaAccountMulticallStorage accountMulticallStorage) { + ACCOUNT_MULTICALL_STORAGE = accountMulticallStorage; } - /// @notice Claims rewards from the target contracts. - /// @param targetData The target data to claim rewards from. + /// @notice Multicalls on behalf of the Llama account. + /// @param targetData The target data to multicall. /// @return returnData The return data from the target calls. - function claimRewards(TargetData[] memory targetData) external onlyDelegateCall returns (bytes[] memory returnData) { + function multicall(TargetData[] memory targetData) external onlyDelegateCall returns (bytes[] memory returnData) { uint256 length = targetData.length; returnData = new bytes[](length); for (uint256 i = 0; i < length; i = LlamaUtils.uncheckedIncrement(i)) { @@ -46,7 +46,7 @@ contract LlamaRewardsClaimAccountExtension is LlamaBaseAccountExtension { bytes4 selector = bytes4(callData); // Check if the target-selector is authorized. - if (!REWARDS_CLAIM_STORAGE.authorizedTargetSelectors(target, selector)) { + if (!ACCOUNT_MULTICALL_STORAGE.authorizedTargetSelectors(target, selector)) { revert UnauthorizedTargetSelector(target, selector); } diff --git a/src/rewards-claimer/LlamaRewardsClaimGuard.sol b/src/account-multicall/LlamaAccountMulticallGuard.sol similarity index 57% rename from src/rewards-claimer/LlamaRewardsClaimGuard.sol rename to src/account-multicall/LlamaAccountMulticallGuard.sol index 13ecd7b..3487ae0 100644 --- a/src/rewards-claimer/LlamaRewardsClaimGuard.sol +++ b/src/account-multicall/LlamaAccountMulticallGuard.sol @@ -1,24 +1,24 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.23; +import {LlamaAccountMulticallExtension} from "src/account-multicall/LlamaAccountMulticallExtension.sol"; import {ILlamaActionGuard} from "src/interfaces/ILlamaActionGuard.sol"; import {ActionInfo} from "src/lib/Structs.sol"; -import {LlamaRewardsClaimAccountExtension} from "src/rewards-claimer/LlamaRewardsClaimAccountExtension.sol"; -/// @title Llama Rewards Claim Guard +/// @title Llama Account Multicall Guard /// @author Llama (devsdosomething@llama.xyz) -/// @notice A guard that only allows the `LlamaRewardsClaimAccountExtension.claimRewards` to be delegate-called +/// @notice A guard that only allows the `LlamaAccountMulticallExtension.multicall` to be delegate-called /// @dev This guard should be used to protect the `execute` function in the `LlamaAccount` contract -contract LlamaRewardsClaimGuard is ILlamaActionGuard { +contract LlamaAccountMulticallGuard is ILlamaActionGuard { /// @dev Thrown if the call is not authorized. error UnauthorizedCall(address target, bytes4 selector, bool withDelegatecall); - /// @notice The address of the `RewardsClaimer` account extension. - LlamaRewardsClaimAccountExtension public immutable REWARDS_CLAIMER; + /// @notice The address of the Llama account multicall extension. + LlamaAccountMulticallExtension public immutable ACCOUNT_MULTICALL_EXTENSION; - /// @dev Initializes the Llama rewards claim guard. - constructor(LlamaRewardsClaimAccountExtension rewardsClaimer) { - REWARDS_CLAIMER = rewardsClaimer; + /// @dev Initializes the Llama account multicall guard. + constructor(LlamaAccountMulticallExtension accountMulticallExtension) { + ACCOUNT_MULTICALL_EXTENSION = accountMulticallExtension; } /// @inheritdoc ILlamaActionGuard @@ -28,9 +28,10 @@ contract LlamaRewardsClaimGuard is ILlamaActionGuard { abi.decode(actionInfo.data[4:], (address, bool, uint256, bytes)); bytes4 selector = bytes4(data); - // Check if the target is the rewards claimer, selector is `claimRewards` and the call type is a delegatecall. + // Check if the target is the Llama account multicall extension, selector is `multicall` and the call type is a + // delegatecall. if ( - target != address(REWARDS_CLAIMER) || selector != LlamaRewardsClaimAccountExtension.claimRewards.selector + target != address(ACCOUNT_MULTICALL_EXTENSION) || selector != LlamaAccountMulticallExtension.multicall.selector || !withDelegatecall ) revert UnauthorizedCall(target, selector, withDelegatecall); } diff --git a/src/rewards-claimer/LlamaRewardsClaimStorage.sol b/src/account-multicall/LlamaAccountMulticallStorage.sol similarity index 89% rename from src/rewards-claimer/LlamaRewardsClaimStorage.sol rename to src/account-multicall/LlamaAccountMulticallStorage.sol index deeb3c3..d902813 100644 --- a/src/rewards-claimer/LlamaRewardsClaimStorage.sol +++ b/src/account-multicall/LlamaAccountMulticallStorage.sol @@ -3,11 +3,11 @@ pragma solidity 0.8.23; import {LlamaUtils} from "src/lib/LlamaUtils.sol"; -/// @title Llama Rewards Claim Storage +/// @title Llama Account Multicall Storage /// @author Llama (devsdosomething@llama.xyz) -/// @notice The storage contract for the `LlamaRewardsClaimAccountExtension` contract. +/// @notice The storage contract for the `LlamaAccountMulticallExtension` contract. /// @dev This is a separate storage contract to prevent storage collisions with the Llama account. -contract LlamaRewardsClaimStorage { +contract LlamaAccountMulticallStorage { /// @dev Struct to hold authorized target-selectors. struct TargetSelectorAuthorization { address target; // The target contract. @@ -27,7 +27,7 @@ contract LlamaRewardsClaimStorage { /// @notice Mapping of all authorized target-selectors. mapping(address target => mapping(bytes4 selector => bool isAuthorized)) public authorizedTargetSelectors; - /// @dev Initializes the Llama rewards claim storage. + /// @dev Initializes the Llama account multicall storage. constructor(address llamaExecutor, TargetSelectorAuthorization[] memory data) { LLAMA_EXECUTOR = llamaExecutor; _setAuthorizedTargetSelectors(data); diff --git a/test/rewards-claimer/LlamaRewardsClaimAccountExtension.t.sol b/test/account-multicall/LlamaAccountMulticallExtension.t.sol similarity index 74% rename from test/rewards-claimer/LlamaRewardsClaimAccountExtension.t.sol rename to test/account-multicall/LlamaAccountMulticallExtension.t.sol index a37c371..75b50c4 100644 --- a/test/rewards-claimer/LlamaRewardsClaimAccountExtension.t.sol +++ b/test/account-multicall/LlamaAccountMulticallExtension.t.sol @@ -6,37 +6,36 @@ import {Test, console2} from "forge-std/Test.sol"; import {IERC20} from "@openzeppelin/token/ERC20/IERC20.sol"; import {MockRewardsContract} from "test/mock/MockRewardsContract.sol"; -import {LlamaRewardsClaimTestSetup} from "test/rewards-claimer/LlamaRewardsClaimTestSetup.sol"; +import {LlamaAccountMulticallTestSetup} from "test/account-multicall/LlamaAccountMulticallTestSetup.sol"; import {ILlamaAccount} from "src/interfaces/ILlamaAccount.sol"; import {ILlamaCore} from "src/interfaces/ILlamaCore.sol"; import {ActionInfo} from "src/lib/Structs.sol"; -import {LlamaRewardsClaimAccountExtension} from "src/rewards-claimer/LlamaRewardsClaimAccountExtension.sol"; -import {LlamaRewardsClaimGuard} from "src/rewards-claimer/LlamaRewardsClaimGuard.sol"; -import {LlamaRewardsClaimStorage} from "src/rewards-claimer/LlamaRewardsClaimStorage.sol"; +import {LlamaAccountMulticallExtension} from "src/account-multicall/LlamaAccountMulticallExtension.sol"; +import {LlamaAccountMulticallStorage} from "src/account-multicall/LlamaAccountMulticallStorage.sol"; import {LlamaBaseAccountExtension} from "src/common/LlamaBaseAccountExtension.sol"; -contract LlamaRewardsClaimAccountExtensionTest is LlamaRewardsClaimTestSetup { +contract LlamaAccountMulticallExtensionTest is LlamaAccountMulticallTestSetup { event ethWithdrawn(address indexed from, address indexed to, uint256 amount); event erc20Withdrawn(IERC20 indexed token, address indexed from, address indexed to, uint256 amount); function setUp() public override { - LlamaRewardsClaimTestSetup.setUp(); + LlamaAccountMulticallTestSetup.setUp(); } } -contract Constructor is LlamaRewardsClaimAccountExtensionTest { - function test_SetsRewardsClaimStorage() public { - assertEq(address(rewardsClaimAccountExtension.REWARDS_CLAIM_STORAGE()), address(rewardsClaimStorage)); +contract Constructor is LlamaAccountMulticallExtensionTest { + function test_SetsAccountMulticallStorage() public { + assertEq(address(accountMulticallExtension.ACCOUNT_MULTICALL_STORAGE()), address(accountMulticallStorage)); } } -contract ClaimRewards is LlamaRewardsClaimAccountExtensionTest { +contract Multicall is LlamaAccountMulticallExtensionTest { function _createAndQueueActionClaimRewards() public returns (ActionInfo memory actionInfo) { - LlamaRewardsClaimAccountExtension.TargetData[] memory targetData = _setupClaimRewardsData(); - bytes memory accountExtensionData = abi.encodeCall(LlamaRewardsClaimAccountExtension.claimRewards, (targetData)); + LlamaAccountMulticallExtension.TargetData[] memory targetData = _setupClaimRewardsData(); + bytes memory accountExtensionData = abi.encodeCall(LlamaAccountMulticallExtension.multicall, (targetData)); bytes memory data = - abi.encodeCall(ILlamaAccount.execute, (address(rewardsClaimAccountExtension), true, 0, accountExtensionData)); + abi.encodeCall(ILlamaAccount.execute, (address(accountMulticallExtension), true, 0, accountExtensionData)); // Create an action to claim rewards. vm.prank(coreTeam1); @@ -52,7 +51,7 @@ contract ClaimRewards is LlamaRewardsClaimAccountExtensionTest { CORE.castApproval(CORE_TEAM_ROLE, actionInfo, ""); } - function test_ClaimRewards() public { + function test_Multicall() public { ActionInfo memory actionInfo = _createAndQueueActionClaimRewards(); assertEq(address(rewardsContract1).balance, 1 ether); @@ -112,20 +111,20 @@ contract ClaimRewards is LlamaRewardsClaimAccountExtensionTest { ActionInfo memory actionInfo = _createAndQueueActionClaimRewards(); // Unauthorize target selector. - LlamaRewardsClaimStorage.TargetSelectorAuthorization[] memory data = - new LlamaRewardsClaimStorage.TargetSelectorAuthorization[](1); - data[0] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + LlamaAccountMulticallStorage.TargetSelectorAuthorization[] memory data = + new LlamaAccountMulticallStorage.TargetSelectorAuthorization[](1); + data[0] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract1), MockRewardsContract.withdrawETH.selector, false ); vm.prank(address(EXECUTOR)); - rewardsClaimStorage.setAuthorizedTargetSelectors(data); + accountMulticallStorage.setAuthorizedTargetSelectors(data); bytes memory expectedErr = abi.encodeWithSelector( ILlamaCore.FailedActionExecution.selector, abi.encodeWithSelector( ILlamaAccount.FailedExecution.selector, abi.encodeWithSelector( - LlamaRewardsClaimAccountExtension.UnauthorizedTargetSelector.selector, + LlamaAccountMulticallExtension.UnauthorizedTargetSelector.selector, address(rewardsContract1), MockRewardsContract.withdrawETH.selector ) @@ -136,8 +135,8 @@ contract ClaimRewards is LlamaRewardsClaimAccountExtensionTest { } function test_RevertIf_NotDelegateCalled() public { - LlamaRewardsClaimAccountExtension.TargetData[] memory targetData = _setupClaimRewardsData(); + LlamaAccountMulticallExtension.TargetData[] memory targetData = _setupClaimRewardsData(); vm.expectRevert(LlamaBaseAccountExtension.OnlyDelegateCall.selector); - rewardsClaimAccountExtension.claimRewards(targetData); + accountMulticallExtension.multicall(targetData); } } diff --git a/test/account-multicall/LlamaAccountMulticallGuard.t.sol b/test/account-multicall/LlamaAccountMulticallGuard.t.sol new file mode 100644 index 0000000..004d64c --- /dev/null +++ b/test/account-multicall/LlamaAccountMulticallGuard.t.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import {Test, console2} from "forge-std/Test.sol"; + +import {LlamaAccountMulticallTestSetup} from "test/account-multicall/LlamaAccountMulticallTestSetup.sol"; + +import {ILlamaAccount} from "src/interfaces/ILlamaAccount.sol"; +import {LlamaAccountMulticallExtension} from "src/account-multicall/LlamaAccountMulticallExtension.sol"; +import {LlamaAccountMulticallGuard} from "src/account-multicall/LlamaAccountMulticallGuard.sol"; + +contract LlamaAccountMulticallGuardTest is LlamaAccountMulticallTestSetup { + function setUp() public override { + LlamaAccountMulticallTestSetup.setUp(); + } +} + +contract Constructor is LlamaAccountMulticallGuardTest { + function test_SetsAccountMulticallExtension() public { + assertEq(address(accountMulticallGuard.ACCOUNT_MULTICALL_EXTENSION()), address(accountMulticallExtension)); + } +} + +contract ValidateActionCreation is LlamaAccountMulticallGuardTest { + function test_PositiveFlow() public { + LlamaAccountMulticallExtension.TargetData[] memory targetData = _setupClaimRewardsData(); + + bytes memory accountExtensionData = abi.encodeCall(LlamaAccountMulticallExtension.multicall, (targetData)); + bytes memory data = + abi.encodeCall(ILlamaAccount.execute, (address(accountMulticallExtension), true, 0, accountExtensionData)); + + assertEq(CORE.actionsCount(), 12); + + vm.prank(coreTeam1); + CORE.createAction(CORE_TEAM_ROLE, STRATEGY, address(ACCOUNT), 0, data, ""); + + assertEq(CORE.actionsCount(), 13); + } + + function test_RevertIf_TargetIsNotAccountMulticallExtension() public { + LlamaAccountMulticallExtension.TargetData[] memory targetData = _setupClaimRewardsData(); + + address dummyTarget = address(0xdeadbeef); + + bytes memory accountExtensionData = abi.encodeCall(LlamaAccountMulticallExtension.multicall, (targetData)); + bytes memory data = abi.encodeCall(ILlamaAccount.execute, (dummyTarget, true, 0, accountExtensionData)); + + vm.prank(coreTeam1); + vm.expectRevert( + abi.encodeWithSelector( + LlamaAccountMulticallGuard.UnauthorizedCall.selector, + dummyTarget, + LlamaAccountMulticallExtension.multicall.selector, + true + ) + ); + CORE.createAction(CORE_TEAM_ROLE, STRATEGY, address(ACCOUNT), 0, data, ""); + } + + function test_RevertIf_SelectorIsNotMulticall() public { + LlamaAccountMulticallExtension.TargetData[] memory targetData = _setupClaimRewardsData(); + + bytes4 dummySelector = bytes4(0); + + bytes memory accountExtensionData = abi.encodeWithSelector(dummySelector, targetData); + bytes memory data = + abi.encodeCall(ILlamaAccount.execute, (address(accountMulticallExtension), true, 0, accountExtensionData)); + + vm.prank(coreTeam1); + vm.expectRevert( + abi.encodeWithSelector( + LlamaAccountMulticallGuard.UnauthorizedCall.selector, address(accountMulticallExtension), dummySelector, true + ) + ); + CORE.createAction(CORE_TEAM_ROLE, STRATEGY, address(ACCOUNT), 0, data, ""); + } + + function test_RevertIf_NotDelegateCall() public { + LlamaAccountMulticallExtension.TargetData[] memory targetData = _setupClaimRewardsData(); + + bytes memory accountExtensionData = abi.encodeCall(LlamaAccountMulticallExtension.multicall, (targetData)); + bytes memory data = + abi.encodeCall(ILlamaAccount.execute, (address(accountMulticallExtension), false, 0, accountExtensionData)); + + vm.prank(coreTeam1); + vm.expectRevert( + abi.encodeWithSelector( + LlamaAccountMulticallGuard.UnauthorizedCall.selector, + address(accountMulticallExtension), + LlamaAccountMulticallExtension.multicall.selector, + false + ) + ); + CORE.createAction(CORE_TEAM_ROLE, STRATEGY, address(ACCOUNT), 0, data, ""); + } +} diff --git a/test/account-multicall/LlamaAccountMulticallStorage.t.sol b/test/account-multicall/LlamaAccountMulticallStorage.t.sol new file mode 100644 index 0000000..dc2e6e0 --- /dev/null +++ b/test/account-multicall/LlamaAccountMulticallStorage.t.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import {Test, console2} from "forge-std/Test.sol"; + +import {LlamaAccountMulticallTestSetup} from "test/account-multicall/LlamaAccountMulticallTestSetup.sol"; + +import {LlamaAccountMulticallStorage} from "src/account-multicall/LlamaAccountMulticallStorage.sol"; + +contract LlamaAccountMulticallStorageTest is LlamaAccountMulticallTestSetup { + event TargetSelectorAuthorized(address indexed target, bytes4 indexed selector, bool isAuthorized); + + function setUp() public override { + LlamaAccountMulticallTestSetup.setUp(); + } +} + +contract Constructor is LlamaAccountMulticallStorageTest { + function test_SetsLlamaExecutor() public { + assertEq(address(accountMulticallStorage.LLAMA_EXECUTOR()), address(EXECUTOR)); + } + + function test_TargetSelectorAuthorization() public { + assertTrue(accountMulticallStorage.authorizedTargetSelectors(address(0xdeadbeef), bytes4(keccak256("withdraw()")))); + } +} + +contract SetAuthorizedTargetSelectors is LlamaAccountMulticallStorageTest { + function test_RevertIf_CallerIsNotLlama() public { + LlamaAccountMulticallStorage.TargetSelectorAuthorization[] memory data = + new LlamaAccountMulticallStorage.TargetSelectorAuthorization[](1); + data[0] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( + address(0xdeadbeef), bytes4(keccak256("withdraw()")), false + ); + + vm.expectRevert(LlamaAccountMulticallStorage.OnlyLlama.selector); + accountMulticallStorage.setAuthorizedTargetSelectors(data); + } + + function test_SetAuthorizedTargetSelectors() public { + LlamaAccountMulticallStorage.TargetSelectorAuthorization[] memory data = + new LlamaAccountMulticallStorage.TargetSelectorAuthorization[](1); + data[0] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( + address(0xdeadbeef), bytes4(keccak256("withdraw()")), false + ); + + assertTrue(accountMulticallStorage.authorizedTargetSelectors(address(0xdeadbeef), bytes4(keccak256("withdraw()")))); + + vm.prank(address(EXECUTOR)); + vm.expectEmit(); + emit TargetSelectorAuthorized(address(0xdeadbeef), bytes4(keccak256("withdraw()")), false); + accountMulticallStorage.setAuthorizedTargetSelectors(data); + + assertFalse(accountMulticallStorage.authorizedTargetSelectors(address(0xdeadbeef), bytes4(keccak256("withdraw()")))); + } +} diff --git a/test/rewards-claimer/LlamaRewardsClaimTestSetup.sol b/test/account-multicall/LlamaAccountMulticallTestSetup.sol similarity index 65% rename from test/rewards-claimer/LlamaRewardsClaimTestSetup.sol rename to test/account-multicall/LlamaAccountMulticallTestSetup.sol index 865ad14..793ce15 100644 --- a/test/rewards-claimer/LlamaRewardsClaimTestSetup.sol +++ b/test/account-multicall/LlamaAccountMulticallTestSetup.sol @@ -10,14 +10,14 @@ import {IERC20} from "@openzeppelin/token/ERC20/IERC20.sol"; import {LlamaPeripheryTestSetup} from "test/LlamaPeripheryTestSetup.sol"; import {MockRewardsContract} from "test/mock/MockRewardsContract.sol"; -import {DeployLlamaRewardsClaimer} from "script/DeployLlamaRewardsClaimer.s.sol"; +import {DeployLlamaAccountMulticall} from "script/DeployLlamaAccountMulticall.s.sol"; import {ILlamaAccount} from "src/interfaces/ILlamaAccount.sol"; import {ILlamaPolicy} from "src/interfaces/ILlamaPolicy.sol"; -import {LlamaRewardsClaimAccountExtension} from "src/rewards-claimer/LlamaRewardsClaimAccountExtension.sol"; -import {LlamaRewardsClaimStorage} from "src/rewards-claimer/LlamaRewardsClaimStorage.sol"; +import {LlamaAccountMulticallExtension} from "src/account-multicall/LlamaAccountMulticallExtension.sol"; +import {LlamaAccountMulticallStorage} from "src/account-multicall/LlamaAccountMulticallStorage.sol"; -contract LlamaRewardsClaimTestSetup is LlamaPeripheryTestSetup, DeployLlamaRewardsClaimer { +contract LlamaAccountMulticallTestSetup is LlamaPeripheryTestSetup, DeployLlamaAccountMulticall { // Sample ERC20 token IERC20 public constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); @@ -31,8 +31,8 @@ contract LlamaRewardsClaimTestSetup is LlamaPeripheryTestSetup, DeployLlamaRewar function setUp() public virtual override { LlamaPeripheryTestSetup.setUp(); - // Deploy the Llama rewards claim contracts. - DeployLlamaRewardsClaimer.run("mockRewardsClaimerConfig.json"); + // Deploy the Llama account multicall contracts. + DeployLlamaAccountMulticall.run("mockAccountMulticallConfig.json"); // Deploy the mock rewards contracts and set LlamaAccount as the reward claimer. // Deal ETH and UNI to the rewards contracts. @@ -58,42 +58,42 @@ contract LlamaRewardsClaimTestSetup is LlamaPeripheryTestSetup, DeployLlamaRewar vm.startPrank(address(EXECUTOR)); // Authorize the rewards contracts to claim rewards. - LlamaRewardsClaimStorage.TargetSelectorAuthorization[] memory data = - new LlamaRewardsClaimStorage.TargetSelectorAuthorization[](10); - data[0] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + LlamaAccountMulticallStorage.TargetSelectorAuthorization[] memory data = + new LlamaAccountMulticallStorage.TargetSelectorAuthorization[](10); + data[0] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract1), MockRewardsContract.withdrawETH.selector, true ); - data[1] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[1] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract1), MockRewardsContract.withdrawERC20.selector, true ); - data[2] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[2] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract2), MockRewardsContract.withdrawETH.selector, true ); - data[3] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[3] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract2), MockRewardsContract.withdrawERC20.selector, true ); - data[4] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[4] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract3), MockRewardsContract.withdrawETH.selector, true ); - data[5] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[5] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract3), MockRewardsContract.withdrawERC20.selector, true ); - data[6] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[6] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract4), MockRewardsContract.withdrawETH.selector, true ); - data[7] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[7] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract4), MockRewardsContract.withdrawERC20.selector, true ); - data[8] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[8] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract5), MockRewardsContract.withdrawETH.selector, true ); - data[9] = LlamaRewardsClaimStorage.TargetSelectorAuthorization( + data[9] = LlamaAccountMulticallStorage.TargetSelectorAuthorization( address(rewardsContract5), MockRewardsContract.withdrawERC20.selector, true ); - rewardsClaimStorage.setAuthorizedTargetSelectors(data); + accountMulticallStorage.setAuthorizedTargetSelectors(data); - // Set the Llama rewards claim guard. - CORE.setGuard(address(ACCOUNT), ILlamaAccount.execute.selector, address(rewardsClaimGuard)); + // Set the Llama account multicall guard. + CORE.setGuard(address(ACCOUNT), ILlamaAccount.execute.selector, address(accountMulticallGuard)); // Assign LlamaAccount.execute permission to Core Team role. POLICY.setRolePermission( @@ -108,40 +108,36 @@ contract LlamaRewardsClaimTestSetup is LlamaPeripheryTestSetup, DeployLlamaRewar // ======== Helpers ======== // ========================= - function _setupClaimRewardsData() - public - view - returns (LlamaRewardsClaimAccountExtension.TargetData[] memory targetData) - { - targetData = new LlamaRewardsClaimAccountExtension.TargetData[](10); - targetData[0] = LlamaRewardsClaimAccountExtension.TargetData( + function _setupClaimRewardsData() public view returns (LlamaAccountMulticallExtension.TargetData[] memory targetData) { + targetData = new LlamaAccountMulticallExtension.TargetData[](10); + targetData[0] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract1), 0, abi.encodeCall(MockRewardsContract.withdrawETH, ()) ); - targetData[1] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[1] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract1), 0, abi.encodeCall(MockRewardsContract.withdrawERC20, (USDC)) ); - targetData[2] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[2] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract2), 0, abi.encodeCall(MockRewardsContract.withdrawETH, ()) ); - targetData[3] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[3] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract2), 0, abi.encodeCall(MockRewardsContract.withdrawERC20, (USDC)) ); - targetData[4] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[4] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract3), 0, abi.encodeCall(MockRewardsContract.withdrawETH, ()) ); - targetData[5] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[5] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract3), 0, abi.encodeCall(MockRewardsContract.withdrawERC20, (USDC)) ); - targetData[6] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[6] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract4), 0, abi.encodeCall(MockRewardsContract.withdrawETH, ()) ); - targetData[7] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[7] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract4), 0, abi.encodeCall(MockRewardsContract.withdrawERC20, (USDC)) ); - targetData[8] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[8] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract5), 0, abi.encodeCall(MockRewardsContract.withdrawETH, ()) ); - targetData[9] = LlamaRewardsClaimAccountExtension.TargetData( + targetData[9] = LlamaAccountMulticallExtension.TargetData( address(rewardsContract5), 0, abi.encodeCall(MockRewardsContract.withdrawERC20, (USDC)) ); } diff --git a/test/rewards-claimer/LlamaRewardsClaimGuard.t.sol b/test/rewards-claimer/LlamaRewardsClaimGuard.t.sol deleted file mode 100644 index 05a3bc1..0000000 --- a/test/rewards-claimer/LlamaRewardsClaimGuard.t.sol +++ /dev/null @@ -1,96 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import {Test, console2} from "forge-std/Test.sol"; - -import {LlamaRewardsClaimTestSetup} from "test/rewards-claimer/LlamaRewardsClaimTestSetup.sol"; - -import {ILlamaAccount} from "src/interfaces/ILlamaAccount.sol"; -import {LlamaRewardsClaimAccountExtension} from "src/rewards-claimer/LlamaRewardsClaimAccountExtension.sol"; -import {LlamaRewardsClaimGuard} from "src/rewards-claimer/LlamaRewardsClaimGuard.sol"; - -contract LlamaRewardsClaimGuardTest is LlamaRewardsClaimTestSetup { - function setUp() public override { - LlamaRewardsClaimTestSetup.setUp(); - } -} - -contract Constructor is LlamaRewardsClaimGuardTest { - function test_SetsRewardsClaimer() public { - assertEq(address(rewardsClaimGuard.REWARDS_CLAIMER()), address(rewardsClaimAccountExtension)); - } -} - -contract ValidateActionCreation is LlamaRewardsClaimGuardTest { - function test_PositiveFlow() public { - LlamaRewardsClaimAccountExtension.TargetData[] memory targetData = _setupClaimRewardsData(); - - bytes memory accountExtensionData = abi.encodeCall(LlamaRewardsClaimAccountExtension.claimRewards, (targetData)); - bytes memory data = - abi.encodeCall(ILlamaAccount.execute, (address(rewardsClaimAccountExtension), true, 0, accountExtensionData)); - - assertEq(CORE.actionsCount(), 12); - - vm.prank(coreTeam1); - CORE.createAction(CORE_TEAM_ROLE, STRATEGY, address(ACCOUNT), 0, data, ""); - - assertEq(CORE.actionsCount(), 13); - } - - function test_RevertIf_TargetIsNotRewardsClaimer() public { - LlamaRewardsClaimAccountExtension.TargetData[] memory targetData = _setupClaimRewardsData(); - - address dummyTarget = address(0xdeadbeef); - - bytes memory accountExtensionData = abi.encodeCall(LlamaRewardsClaimAccountExtension.claimRewards, (targetData)); - bytes memory data = abi.encodeCall(ILlamaAccount.execute, (dummyTarget, true, 0, accountExtensionData)); - - vm.prank(coreTeam1); - vm.expectRevert( - abi.encodeWithSelector( - LlamaRewardsClaimGuard.UnauthorizedCall.selector, - dummyTarget, - LlamaRewardsClaimAccountExtension.claimRewards.selector, - true - ) - ); - CORE.createAction(CORE_TEAM_ROLE, STRATEGY, address(ACCOUNT), 0, data, ""); - } - - function test_RevertIf_SelectorIsNotClaimRewards() public { - LlamaRewardsClaimAccountExtension.TargetData[] memory targetData = _setupClaimRewardsData(); - - bytes4 dummySelector = bytes4(0); - - bytes memory accountExtensionData = abi.encodeWithSelector(dummySelector, targetData); - bytes memory data = - abi.encodeCall(ILlamaAccount.execute, (address(rewardsClaimAccountExtension), true, 0, accountExtensionData)); - - vm.prank(coreTeam1); - vm.expectRevert( - abi.encodeWithSelector( - LlamaRewardsClaimGuard.UnauthorizedCall.selector, address(rewardsClaimAccountExtension), dummySelector, true - ) - ); - CORE.createAction(CORE_TEAM_ROLE, STRATEGY, address(ACCOUNT), 0, data, ""); - } - - function test_RevertIf_NotDelegateCall() public { - LlamaRewardsClaimAccountExtension.TargetData[] memory targetData = _setupClaimRewardsData(); - - bytes memory accountExtensionData = abi.encodeCall(LlamaRewardsClaimAccountExtension.claimRewards, (targetData)); - bytes memory data = - abi.encodeCall(ILlamaAccount.execute, (address(rewardsClaimAccountExtension), false, 0, accountExtensionData)); - - vm.prank(coreTeam1); - vm.expectRevert( - abi.encodeWithSelector( - LlamaRewardsClaimGuard.UnauthorizedCall.selector, - address(rewardsClaimAccountExtension), - LlamaRewardsClaimAccountExtension.claimRewards.selector, - false - ) - ); - CORE.createAction(CORE_TEAM_ROLE, STRATEGY, address(ACCOUNT), 0, data, ""); - } -} diff --git a/test/rewards-claimer/LlamaRewardsClaimStorage.t.sol b/test/rewards-claimer/LlamaRewardsClaimStorage.t.sol deleted file mode 100644 index 8d1a2e1..0000000 --- a/test/rewards-claimer/LlamaRewardsClaimStorage.t.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import {Test, console2} from "forge-std/Test.sol"; - -import {LlamaRewardsClaimTestSetup} from "test/rewards-claimer/LlamaRewardsClaimTestSetup.sol"; - -import {LlamaRewardsClaimStorage} from "src/rewards-claimer/LlamaRewardsClaimStorage.sol"; - -contract LlamaRewardsClaimStorageTest is LlamaRewardsClaimTestSetup { - event TargetSelectorAuthorized(address indexed target, bytes4 indexed selector, bool isAuthorized); - - function setUp() public override { - LlamaRewardsClaimTestSetup.setUp(); - } -} - -contract Constructor is LlamaRewardsClaimStorageTest { - function test_SetsLlamaExecutor() public { - assertEq(address(rewardsClaimStorage.LLAMA_EXECUTOR()), address(EXECUTOR)); - } - - function test_TargetSelectorAuthorization() public { - assertTrue(rewardsClaimStorage.authorizedTargetSelectors(address(0xdeadbeef), bytes4(keccak256("withdraw()")))); - } -} - -contract SetAuthorizedTargetSelectors is LlamaRewardsClaimStorageTest { - function test_RevertIf_CallerIsNotLlama() public { - LlamaRewardsClaimStorage.TargetSelectorAuthorization[] memory data = - new LlamaRewardsClaimStorage.TargetSelectorAuthorization[](1); - data[0] = - LlamaRewardsClaimStorage.TargetSelectorAuthorization(address(0xdeadbeef), bytes4(keccak256("withdraw()")), false); - - vm.expectRevert(LlamaRewardsClaimStorage.OnlyLlama.selector); - rewardsClaimStorage.setAuthorizedTargetSelectors(data); - } - - function test_SetAuthorizedTargetSelectors() public { - LlamaRewardsClaimStorage.TargetSelectorAuthorization[] memory data = - new LlamaRewardsClaimStorage.TargetSelectorAuthorization[](1); - data[0] = - LlamaRewardsClaimStorage.TargetSelectorAuthorization(address(0xdeadbeef), bytes4(keccak256("withdraw()")), false); - - assertTrue(rewardsClaimStorage.authorizedTargetSelectors(address(0xdeadbeef), bytes4(keccak256("withdraw()")))); - - vm.prank(address(EXECUTOR)); - vm.expectEmit(); - emit TargetSelectorAuthorized(address(0xdeadbeef), bytes4(keccak256("withdraw()")), false); - rewardsClaimStorage.setAuthorizedTargetSelectors(data); - - assertFalse(rewardsClaimStorage.authorizedTargetSelectors(address(0xdeadbeef), bytes4(keccak256("withdraw()")))); - } -}