diff --git a/script/DeployLlamaFactory.s.sol b/script/DeployLlamaFactory.s.sol index 9e1362851..18aec2988 100644 --- a/script/DeployLlamaFactory.s.sol +++ b/script/DeployLlamaFactory.s.sol @@ -9,6 +9,7 @@ import {LlamaFactory} from "src/LlamaFactory.sol"; import {LlamaLens} from "src/LlamaLens.sol"; import {LlamaPolicy} from "src/LlamaPolicy.sol"; import {LlamaPolicyMetadata} from "src/LlamaPolicyMetadata.sol"; +import {LlamaGovernanceScript} from "src/llama-scripts/LlamaGovernanceScript.sol"; import {LlamaAbsolutePeerReview} from "src/strategies/absolute/LlamaAbsolutePeerReview.sol"; import {LlamaAbsoluteQuorum} from "src/strategies/absolute/LlamaAbsoluteQuorum.sol"; import {LlamaRelativeHolderQuorum} from "src/strategies/relative/LlamaRelativeHolderQuorum.sol"; @@ -34,6 +35,9 @@ contract DeployLlamaFactory is Script { LlamaFactory factory; LlamaLens lens; + // Llama scripts + LlamaGovernanceScript governanceScript; + function run() public { DeployUtils.print(string.concat("Deploying Llama factory to chain:", vm.toString(block.chainid))); @@ -117,5 +121,9 @@ contract DeployLlamaFactory is Script { vm.broadcast(); absolutePeerReviewLogic = new LlamaAbsolutePeerReview(); DeployUtils.print(string.concat(" LlamaAbsolutePeerReviewLogic:", vm.toString(address(absolutePeerReviewLogic)))); + + vm.broadcast(); + governanceScript = new LlamaGovernanceScript(); + DeployUtils.print(string.concat(" LlamaGovernanceScript:", vm.toString(address(governanceScript)))); } } diff --git a/src/llama-scripts/LlamaGovernanceScript.sol b/src/llama-scripts/LlamaGovernanceScript.sol index 8166af211..aec05337c 100644 --- a/src/llama-scripts/LlamaGovernanceScript.sol +++ b/src/llama-scripts/LlamaGovernanceScript.sol @@ -1,14 +1,19 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import {LlamaBaseScript} from "src/llama-scripts/LlamaBaseScript.sol"; +import {Clones} from "@openzeppelin/proxy/Clones.sol"; + +import {LlamaAccount} from "src/accounts/LlamaAccount.sol"; +import {ILlamaAccount} from "src/interfaces/ILlamaAccount.sol"; import {ILlamaStrategy} from "src/interfaces/ILlamaStrategy.sol"; +import {LlamaBaseScript} from "src/llama-scripts/LlamaBaseScript.sol"; +import {LlamaUtils} from "src/lib/LlamaUtils.sol"; +import {PermissionData, RoleHolderData, RolePermissionData} from "src/lib/Structs.sol"; +import {RoleDescription} from "src/lib/UDVTs.sol"; import {LlamaCore} from "src/LlamaCore.sol"; import {LlamaExecutor} from "src/LlamaExecutor.sol"; +import {LlamaLens} from "src/LlamaLens.sol"; import {LlamaPolicy} from "src/LlamaPolicy.sol"; -import {LlamaUtils} from "src/lib/LlamaUtils.sol"; -import {RoleHolderData, RolePermissionData} from "src/lib/Structs.sol"; -import {RoleDescription} from "src/lib/UDVTs.sol"; /// @title Llama Governance Script /// @author Llama (devsdosomething@llama.xyz) @@ -36,6 +41,11 @@ contract LlamaGovernanceScript is LlamaBaseScript { bytes[] strategies; // Array of configurations to initialize new strategies with. } + struct CreateAccounts { + ILlamaAccount accountLogic; + bytes config; + } + // ======================== // ======== Errors ======== // ======================== @@ -52,6 +62,10 @@ contract LlamaGovernanceScript is LlamaBaseScript { /// @param target The target address provided. error UnauthorizedTarget(address target); + /// @dev The target address is not the created account. + /// @param target The target address provided. + error TargetIsNotAccount(address target); + // ======================================= // ======== Arbitrary Aggregation ======== // ======================================= @@ -89,22 +103,22 @@ contract LlamaGovernanceScript is LlamaBaseScript { /// @notice Initialize new roles and set their holders with the provided data. /// @param description Array of role descriptions to initialize. /// @param _setRoleHolders Array of role holders to set. - function initializeRolesAndSetRoleHolders( - RoleDescription[] calldata description, - RoleHolderData[] calldata _setRoleHolders - ) external onlyDelegateCall { - initializeRoles(description); + function initRolesAndSetRoleHolders(RoleDescription[] calldata description, RoleHolderData[] calldata _setRoleHolders) + external + onlyDelegateCall + { + initRoles(description); setRoleHolders(_setRoleHolders); } /// @notice Initialize new roles and set their permissions with the provided data. /// @param description Array of role descriptions to initialize. /// @param _setRolePermissions Array of role permissions to set. - function initializeRolesAndSetRolePermissions( + function initRolesAndSetRolePermissions( RoleDescription[] calldata description, RolePermissionData[] calldata _setRolePermissions ) external onlyDelegateCall { - initializeRoles(description); + initRoles(description); setRolePermissions(_setRolePermissions); } @@ -112,12 +126,12 @@ contract LlamaGovernanceScript is LlamaBaseScript { /// @param description Array of role descriptions to initialize. /// @param _setRoleHolders Array of role holders to set. /// @param _setRolePermissions Array of role permissions to set. - function initializeRolesAndSetRoleHoldersAndSetRolePermissions( + function initRolesAndHoldersAndPermissions( RoleDescription[] calldata description, RoleHolderData[] calldata _setRoleHolders, RolePermissionData[] calldata _setRolePermissions ) external onlyDelegateCall { - initializeRoles(description); + initRoles(description); setRoleHolders(_setRoleHolders); setRolePermissions(_setRolePermissions); } @@ -138,14 +152,14 @@ contract LlamaGovernanceScript is LlamaBaseScript { /// @param _createStrategies Struct of data for the `createStrategies` method in `LlamaCore`. /// @param description Array of role descriptions to initialize. /// @param _setRoleHolders Array of role holders to set. - function createNewStrategiesAndInitializeRolesAndSetRoleHolders( + function createStrategiesAndInitRolesAndHolders( CreateStrategies calldata _createStrategies, RoleDescription[] calldata description, RoleHolderData[] calldata _setRoleHolders ) external onlyDelegateCall { (LlamaCore core,) = _context(); core.createStrategies(_createStrategies.llamaStrategyLogic, _createStrategies.strategies); - initializeRoles(description); + initRoles(description); setRoleHolders(_setRoleHolders); } @@ -167,7 +181,7 @@ contract LlamaGovernanceScript is LlamaBaseScript { /// @param description Array of role descriptions to initialize. /// @param _setRoleHolders Array of role holders to set. /// @param _setRolePermissions Array of role permissions to set. - function createNewStrategiesAndInitializeRolesAndSetRoleHoldersAndSetRolePermissions( + function createStrategiesWithRolesAndPermissions( CreateStrategies calldata _createStrategies, RoleDescription[] calldata description, RoleHolderData[] calldata _setRoleHolders, @@ -175,7 +189,7 @@ contract LlamaGovernanceScript is LlamaBaseScript { ) external onlyDelegateCall { (LlamaCore core,) = _context(); core.createStrategies(_createStrategies.llamaStrategyLogic, _createStrategies.strategies); - initializeRoles(description); + initRoles(description); setRoleHolders(_setRoleHolders); setRolePermissions(_setRolePermissions); } @@ -195,7 +209,7 @@ contract LlamaGovernanceScript is LlamaBaseScript { /// @param _revokePolicies Array of policies to revoke. /// @param _updateRoleDescriptions Array of role descriptions to update. /// @param _setRoleHolders Array of role holders to set. - function revokePoliciesAndUpdateRoleDescriptionsAndSetRoleHolders( + function revokePoliciesAndSetRoleDescsAndHolders( address[] calldata _revokePolicies, UpdateRoleDescription[] calldata _updateRoleDescriptions, RoleHolderData[] calldata _setRoleHolders @@ -205,17 +219,115 @@ contract LlamaGovernanceScript is LlamaBaseScript { setRoleHolders(_setRoleHolders); } + /// @notice Create Account and set common permissions to allow the given role to approve and transfer tokens. + /// @param account Account to create. + /// @param _permissions Array of permissions to set. + function createAccountAndSetRolePermissions( + CreateAccounts calldata account, + RolePermissionData[] calldata _permissions + ) external onlyDelegateCall { + (LlamaCore core,) = _context(); + bytes[] memory config = new bytes[](1); + config[0] = account.config; + core.createAccounts(account.accountLogic, config); + address accountAddress = + Clones.predictDeterministicAddress(address(account.accountLogic), keccak256(account.config), address(core)); + for (uint256 i = 0; i < _permissions.length; i = LlamaUtils.uncheckedIncrement(i)) { + if (_permissions[i].permissionData.target != accountAddress) { + revert TargetIsNotAccount(_permissions[i].permissionData.target); + } + } + setRolePermissions(_permissions); + } + + /// @notice Sets script authorization and sets role permissions. + /// @param script Address of the script to set authorization for. + /// @param authorized Whether or not the script is authorized. This also determines if `hasPermission` is true or + /// false. + /// @param role Role to set permissions for. + /// @param selectors Array of selectors to use as part of the permissions. + /// @param strategies Array of strategies to use as part of the permissions. + function setScriptAuthAndSetPermissions( + address script, + bool authorized, + uint8 role, + bytes4[] calldata selectors, + ILlamaStrategy[] calldata strategies + ) external onlyDelegateCall { + (LlamaCore core,) = _context(); + if (selectors.length != strategies.length) revert MismatchedArrayLengths(); + core.setScriptAuthorization(script, authorized); + RolePermissionData[] memory permissions = new RolePermissionData[](selectors.length); + for (uint256 i = 0; i < selectors.length; i = LlamaUtils.uncheckedIncrement(i)) { + permissions[i] = + RolePermissionData(role, PermissionData(address(script), selectors[i], strategies[i]), authorized); + } + setRolePermissions(permissions); + } + + // ======================================== + // ======== Batch Core Functions ======== + // ======================================== + + /// @notice Batch set strategy logic authorizations. + /// @param strategyLogics Array of strategy logic contracts to set authorization for. + /// @param authorized Boolean to determine whether an address is being authorized or unauthorized. + function setStrategyLogicAuthorizations(ILlamaStrategy[] calldata strategyLogics, bool authorized) + external + onlyDelegateCall + { + (LlamaCore core,) = _context(); + for (uint256 i = 0; i < strategyLogics.length; i = LlamaUtils.uncheckedIncrement(i)) { + core.setStrategyLogicAuthorization(strategyLogics[i], authorized); + } + } + + /// @notice Batch set account logic authorizations. + /// @param accountLogics Array of account logic contracts to set authorization for. + /// @param authorized Boolean to determine whether an address is being authorized or unauthorized. + function setAccountLogicAuthorizations(ILlamaAccount[] calldata accountLogics, bool authorized) + external + onlyDelegateCall + { + (LlamaCore core,) = _context(); + for (uint256 i = 0; i < accountLogics.length; i = LlamaUtils.uncheckedIncrement(i)) { + core.setAccountLogicAuthorization(accountLogics[i], authorized); + } + } + + /// @notice Batch set strategy authorizations. + /// @param strategies Array of strategies to set authorization for. + /// @param authorized Boolean to determine whether a strategy is being authorized or unauthorized. + function setStrategyAuthorizations(ILlamaStrategy[] calldata strategies, bool authorized) external onlyDelegateCall { + (LlamaCore core,) = _context(); + for (uint256 i = 0; i < strategies.length; i = LlamaUtils.uncheckedIncrement(i)) { + core.setStrategyAuthorization(strategies[i], authorized); + } + } + + /// @notice Set strategy logic authorization and create new strategies. + /// @param strategyLogic Strategy logic contract to set authorization for. + /// @param strategies Array of configurations to initialize new strategies with. + function setStrategyLogicAuthAndNewStrategies(ILlamaStrategy strategyLogic, bytes[] calldata strategies) + external + onlyDelegateCall + { + (LlamaCore core,) = _context(); + core.setStrategyLogicAuthorization(strategyLogic, true); + core.createStrategies(strategyLogic, strategies); + } + // ======================================== // ======== Batch Policy Functions ======== // ======================================== /// @notice Batch initialize new roles with the provided data. - /// @param description Array of role descriptions to initialize. - function initializeRoles(RoleDescription[] calldata description) public onlyDelegateCall { + /// @param descriptions Array of role descriptions to initialize. + function initRoles(RoleDescription[] calldata descriptions) public onlyDelegateCall { (, LlamaPolicy policy) = _context(); - uint256 length = description.length; + uint256 length = descriptions.length; for (uint256 i = 0; i < length; i = LlamaUtils.uncheckedIncrement(i)) { - policy.initializeRole(description[i]); + policy.initializeRole(descriptions[i]); } } @@ -236,7 +348,7 @@ contract LlamaGovernanceScript is LlamaBaseScript { /// @notice Batch set role permissions with the provided data. /// @param _setRolePermissions Array of role permissions to set. - function setRolePermissions(RolePermissionData[] calldata _setRolePermissions) public onlyDelegateCall { + function setRolePermissions(RolePermissionData[] memory _setRolePermissions) public onlyDelegateCall { (, LlamaPolicy policy) = _context(); uint256 length = _setRolePermissions.length; for (uint256 i = 0; i < length; i = LlamaUtils.uncheckedIncrement(i)) { diff --git a/test/llama-scripts/LlamaGovernanceScript.t.sol b/test/llama-scripts/LlamaGovernanceScript.t.sol index a382b8405..c40256c3c 100644 --- a/test/llama-scripts/LlamaGovernanceScript.t.sol +++ b/test/llama-scripts/LlamaGovernanceScript.t.sol @@ -8,6 +8,7 @@ import {Roles, LlamaTestSetup} from "test/utils/LlamaTestSetup.sol"; import {LlamaAccount} from "src/accounts/LlamaAccount.sol"; import {ILlamaAccount} from "src/interfaces/ILlamaAccount.sol"; import {ILlamaStrategy} from "src/interfaces/ILlamaStrategy.sol"; +import {LlamaUtils} from "src/lib/LlamaUtils.sol"; import {ActionInfo, PermissionData, RoleHolderData, RolePermissionData} from "src/lib/Structs.sol"; import {RoleDescription} from "src/lib/UDVTs.sol"; import {LlamaGovernanceScript} from "src/llama-scripts/LlamaGovernanceScript.sol"; @@ -17,12 +18,15 @@ import {DeployUtils} from "script/DeployUtils.sol"; contract LlamaGovernanceScriptTest is LlamaTestSetup { event AccountCreated(ILlamaAccount account, ILlamaAccount indexed accountLogic, bytes initializationData); + event AccountLogicAuthorizationSet(ILlamaAccount indexed accountLogic, bool authorized); event RoleAssigned(address indexed policyholder, uint8 indexed role, uint64 expiration, uint96 quantity); event RoleInitialized(uint8 indexed role, RoleDescription description); event RolePermissionAssigned( uint8 indexed role, bytes32 indexed permissionId, PermissionData permissionData, bool hasPermission ); + event ScriptAuthorizationSet(address indexed script, bool authorized); event StrategyAuthorizationSet(ILlamaStrategy indexed strategy, bool authorized); + event StrategyLogicAuthorizationSet(ILlamaStrategy indexed strategyLogic, bool authorized); event StrategyCreated(ILlamaStrategy strategy, ILlamaStrategy indexed strategyLogic, bytes initializationData); mapping(uint8 => uint96) public rolesHoldersSeen; @@ -31,33 +35,42 @@ contract LlamaGovernanceScriptTest is LlamaTestSetup { uint8[] public roles; address[] public revokePolicies; - LlamaGovernanceScript governanceScript; + LlamaGovernanceScript govScript; bytes4 public constant AGGREGATE_SELECTOR = LlamaGovernanceScript.aggregate.selector; - bytes4 public constant INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR = - LlamaGovernanceScript.initializeRolesAndSetRoleHolders.selector; + bytes4 public constant INIT_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR = + LlamaGovernanceScript.initRolesAndSetRoleHolders.selector; bytes4 public constant INITIALIZE_ROLES_AND_SET_ROLE_PERMISSIONS_SELECTOR = - LlamaGovernanceScript.initializeRolesAndSetRolePermissions.selector; - bytes4 public constant INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_AND_SET_ROLE_PERMISSIONS_SELECTOR = - LlamaGovernanceScript.initializeRolesAndSetRoleHoldersAndSetRolePermissions.selector; + LlamaGovernanceScript.initRolesAndSetRolePermissions.selector; + bytes4 public constant INIT_ROLES_AND_HOLDERS_AND_PERMISSIONS_SELECTOR = + LlamaGovernanceScript.initRolesAndHoldersAndPermissions.selector; bytes4 public constant CREATE_NEW_STRATEGIES_AND_SET_ROLE_HOLDERS_SELECTOR = LlamaGovernanceScript.createNewStrategiesAndSetRoleHolders.selector; - bytes4 public constant CREATE_NEW_STRATEGIES_AND_INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR = - LlamaGovernanceScript.createNewStrategiesAndInitializeRolesAndSetRoleHolders.selector; + bytes4 public constant CREATE_STRATEGIES_AND_INIT_ROLES_AND_HOLDERS_SELECTOR = + LlamaGovernanceScript.createStrategiesAndInitRolesAndHolders.selector; bytes4 public constant CREATE_NEW_STRATEGIES_AND_SET_ROLE_PERMISSIONS_SELECTOR = LlamaGovernanceScript.createNewStrategiesAndSetRolePermissions.selector; - bytes4 public constant - CREATE_NEW_STRATEGIES_AND_INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_AND_SET_ROLE_PERMISSIONS_SELECTOR = - LlamaGovernanceScript.createNewStrategiesAndInitializeRolesAndSetRoleHoldersAndSetRolePermissions.selector; + bytes4 public constant CREATE_STRATEGIES_WITH_ROLES_AND_PERMISSIONS_SELECTOR = + LlamaGovernanceScript.createStrategiesWithRolesAndPermissions.selector; bytes4 public constant REVOKE_POLICIES_AND_UPDATE_ROLE_DESCRIPTIONS_SELECTOR = LlamaGovernanceScript.revokePoliciesAndUpdateRoleDescriptions.selector; - bytes4 public constant REVOKE_POLICIES_AND_UPDATE_ROLE_DESCRIPTIONS_AND_SET_ROLE_HOLDERS_SELECTOR = - LlamaGovernanceScript.revokePoliciesAndUpdateRoleDescriptionsAndSetRoleHolders.selector; - bytes4 public constant INITIALIZE_ROLES_SELECTOR = LlamaGovernanceScript.initializeRoles.selector; + bytes4 public constant REVOKE_POLICIES_AND_SET_ROLE_DESCS_AND_HOLDERS_SELECTOR = + LlamaGovernanceScript.revokePoliciesAndSetRoleDescsAndHolders.selector; + bytes4 public constant INIT_ROLES_SELECTOR = LlamaGovernanceScript.initRoles.selector; bytes4 public constant SET_ROLE_HOLDERS_SELECTOR = LlamaGovernanceScript.setRoleHolders.selector; bytes4 public constant SET_ROLE_PERMISSIONS_SELECTOR = LlamaGovernanceScript.setRolePermissions.selector; bytes4 public constant REVOKE_POLICIES_SELECTOR = LlamaGovernanceScript.revokePolicies.selector; bytes4 public constant UPDATE_ROLE_DESCRIPTIONS_SELECTOR = LlamaGovernanceScript.updateRoleDescriptions.selector; + bytes4 public constant SET_STRATEGY_LOGIC_AUTHORIZATIONS_SELECTOR = + LlamaGovernanceScript.setStrategyLogicAuthorizations.selector; + bytes4 public constant SET_STRATEGY_AUTHORIZATIONS_SELECTOR = LlamaGovernanceScript.setStrategyAuthorizations.selector; + bytes4 public constant SET_ACCOUNT_LOGIC_AUTHORIZATIONS_SELECTOR = + LlamaGovernanceScript.setAccountLogicAuthorizations.selector; + bytes4 public constant SET_STRATEGY_LOGIC_AUTH_AND_NEW_STRATEGIES_SELECTOR = + LlamaGovernanceScript.setStrategyLogicAuthAndNewStrategies.selector; + bytes4 SET_SCRIPT_AUTH_AND_SET_PERMISSIONS_SELECTOR = LlamaGovernanceScript.setScriptAuthAndSetPermissions.selector; + bytes4 CREATE_ACCOUNT_AND_SET_ROLE_PERMISSIONS_SELECTOR = + LlamaGovernanceScript.createAccountAndSetRolePermissions.selector; PermissionData public executeActionPermission; PermissionData public aggregatePermission; @@ -69,54 +82,65 @@ contract LlamaGovernanceScriptTest is LlamaTestSetup { PermissionData public createNewStrategiesAndSetRolePermissionsPermission; PermissionData public createNewStrategiesAndNewRolesAndSetRoleHoldersAndSetRolePermissionsPermission; PermissionData public revokePoliciesAndUpdateRoleDescriptionsPermission; - PermissionData public revokePoliciesAndUpdateRoleDescriptionsAndSetRoleHoldersPermission; + PermissionData public revokePoliciesAndSetRoleDescsAndHolders; PermissionData public initializeRolesPermission; PermissionData public setRoleHoldersPermission; PermissionData public setRolePermissionsPermission; PermissionData public revokePoliciesPermission; PermissionData public updateRoleDescriptionPerimssion; + PermissionData public setStrategyLogicAuthorizationsPermission; + PermissionData public setStrategyAuthorizationsPermission; + PermissionData public setAccountLogicAuthorizationsPermission; + PermissionData public setStrategyLogicAuthAndNewStrategiesPermission; + PermissionData public setScriptAuthAndSetPermissionsPermission; + PermissionData public createAccountAndSetRolePermissionsPermission; function setUp() public virtual override { LlamaTestSetup.setUp(); - governanceScript = new LlamaGovernanceScript(); + govScript = new LlamaGovernanceScript(); vm.startPrank(address(mpExecutor)); - mpCore.setScriptAuthorization(address(governanceScript), true); + mpCore.setScriptAuthorization(address(govScript), true); - executeActionPermission = PermissionData(address(governanceScript), EXECUTE_ACTION_SELECTOR, mpStrategy2); - aggregatePermission = PermissionData(address(governanceScript), AGGREGATE_SELECTOR, mpStrategy2); + executeActionPermission = PermissionData(address(govScript), EXECUTE_ACTION_SELECTOR, mpStrategy2); + aggregatePermission = PermissionData(address(govScript), AGGREGATE_SELECTOR, mpStrategy2); initializeRolesAndSetRoleHoldersPermission = - PermissionData(address(governanceScript), INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR, mpStrategy2); + PermissionData(address(govScript), INIT_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR, mpStrategy2); initializeRolesAndSetRolePermissionsPermission = - PermissionData(address(governanceScript), INITIALIZE_ROLES_AND_SET_ROLE_PERMISSIONS_SELECTOR, mpStrategy2); - initializeRolesAndSetRoleHoldersAndSetRolePermissionsPermission = PermissionData( - address(governanceScript), INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_AND_SET_ROLE_PERMISSIONS_SELECTOR, mpStrategy2 - ); + PermissionData(address(govScript), INITIALIZE_ROLES_AND_SET_ROLE_PERMISSIONS_SELECTOR, mpStrategy2); + initializeRolesAndSetRoleHoldersAndSetRolePermissionsPermission = + PermissionData(address(govScript), INIT_ROLES_AND_HOLDERS_AND_PERMISSIONS_SELECTOR, mpStrategy2); createNewStrategiesAndSetRoleHoldersPermission = - PermissionData(address(governanceScript), CREATE_NEW_STRATEGIES_AND_SET_ROLE_HOLDERS_SELECTOR, mpStrategy2); - createNewStrategiesAndInitializeRolesAndSetRoleHoldersPermission = PermissionData( - address(governanceScript), CREATE_NEW_STRATEGIES_AND_INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR, mpStrategy2 - ); + PermissionData(address(govScript), CREATE_NEW_STRATEGIES_AND_SET_ROLE_HOLDERS_SELECTOR, mpStrategy2); + createNewStrategiesAndInitializeRolesAndSetRoleHoldersPermission = + PermissionData(address(govScript), CREATE_STRATEGIES_AND_INIT_ROLES_AND_HOLDERS_SELECTOR, mpStrategy2); createNewStrategiesAndSetRolePermissionsPermission = - PermissionData(address(governanceScript), CREATE_NEW_STRATEGIES_AND_SET_ROLE_PERMISSIONS_SELECTOR, mpStrategy2); - createNewStrategiesAndNewRolesAndSetRoleHoldersAndSetRolePermissionsPermission = PermissionData( - address(governanceScript), - CREATE_NEW_STRATEGIES_AND_INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_AND_SET_ROLE_PERMISSIONS_SELECTOR, - mpStrategy2 - ); + PermissionData(address(govScript), CREATE_NEW_STRATEGIES_AND_SET_ROLE_PERMISSIONS_SELECTOR, mpStrategy2); + createNewStrategiesAndNewRolesAndSetRoleHoldersAndSetRolePermissionsPermission = + PermissionData(address(govScript), CREATE_STRATEGIES_WITH_ROLES_AND_PERMISSIONS_SELECTOR, mpStrategy2); revokePoliciesAndUpdateRoleDescriptionsPermission = - PermissionData(address(governanceScript), REVOKE_POLICIES_AND_UPDATE_ROLE_DESCRIPTIONS_SELECTOR, mpStrategy2); - revokePoliciesAndUpdateRoleDescriptionsAndSetRoleHoldersPermission = PermissionData( - address(governanceScript), REVOKE_POLICIES_AND_UPDATE_ROLE_DESCRIPTIONS_AND_SET_ROLE_HOLDERS_SELECTOR, mpStrategy2 - ); - initializeRolesPermission = PermissionData(address(governanceScript), INITIALIZE_ROLES_SELECTOR, mpStrategy2); - setRoleHoldersPermission = PermissionData(address(governanceScript), SET_ROLE_HOLDERS_SELECTOR, mpStrategy2); - setRolePermissionsPermission = PermissionData(address(governanceScript), SET_ROLE_PERMISSIONS_SELECTOR, mpStrategy2); - revokePoliciesPermission = PermissionData(address(governanceScript), REVOKE_POLICIES_SELECTOR, mpStrategy2); - updateRoleDescriptionPerimssion = - PermissionData(address(governanceScript), UPDATE_ROLE_DESCRIPTIONS_SELECTOR, mpStrategy2); + PermissionData(address(govScript), REVOKE_POLICIES_AND_UPDATE_ROLE_DESCRIPTIONS_SELECTOR, mpStrategy2); + revokePoliciesAndSetRoleDescsAndHolders = + PermissionData(address(govScript), REVOKE_POLICIES_AND_SET_ROLE_DESCS_AND_HOLDERS_SELECTOR, mpStrategy2); + initializeRolesPermission = PermissionData(address(govScript), INIT_ROLES_SELECTOR, mpStrategy2); + setRoleHoldersPermission = PermissionData(address(govScript), SET_ROLE_HOLDERS_SELECTOR, mpStrategy2); + setRolePermissionsPermission = PermissionData(address(govScript), SET_ROLE_PERMISSIONS_SELECTOR, mpStrategy2); + revokePoliciesPermission = PermissionData(address(govScript), REVOKE_POLICIES_SELECTOR, mpStrategy2); + updateRoleDescriptionPerimssion = PermissionData(address(govScript), UPDATE_ROLE_DESCRIPTIONS_SELECTOR, mpStrategy2); + setStrategyLogicAuthorizationsPermission = + PermissionData(address(govScript), SET_STRATEGY_LOGIC_AUTHORIZATIONS_SELECTOR, mpStrategy2); + setStrategyAuthorizationsPermission = + PermissionData(address(govScript), SET_STRATEGY_AUTHORIZATIONS_SELECTOR, mpStrategy2); + setAccountLogicAuthorizationsPermission = + PermissionData(address(govScript), SET_ACCOUNT_LOGIC_AUTHORIZATIONS_SELECTOR, mpStrategy2); + setStrategyLogicAuthAndNewStrategiesPermission = + PermissionData(address(govScript), SET_STRATEGY_LOGIC_AUTH_AND_NEW_STRATEGIES_SELECTOR, mpStrategy2); + setScriptAuthAndSetPermissionsPermission = + PermissionData(address(govScript), SET_SCRIPT_AUTH_AND_SET_PERMISSIONS_SELECTOR, mpStrategy2); + createAccountAndSetRolePermissionsPermission = + PermissionData(address(govScript), CREATE_ACCOUNT_AND_SET_ROLE_PERMISSIONS_SELECTOR, mpStrategy2); mpPolicy.setRolePermission(uint8(Roles.ActionCreator), executeActionPermission, true); mpPolicy.setRolePermission(uint8(Roles.ActionCreator), aggregatePermission, true); @@ -134,14 +158,18 @@ contract LlamaGovernanceScriptTest is LlamaTestSetup { uint8(Roles.ActionCreator), createNewStrategiesAndNewRolesAndSetRoleHoldersAndSetRolePermissionsPermission, true ); mpPolicy.setRolePermission(uint8(Roles.ActionCreator), revokePoliciesAndUpdateRoleDescriptionsPermission, true); - mpPolicy.setRolePermission( - uint8(Roles.ActionCreator), revokePoliciesAndUpdateRoleDescriptionsAndSetRoleHoldersPermission, true - ); + mpPolicy.setRolePermission(uint8(Roles.ActionCreator), revokePoliciesAndSetRoleDescsAndHolders, true); mpPolicy.setRolePermission(uint8(Roles.ActionCreator), initializeRolesPermission, true); mpPolicy.setRolePermission(uint8(Roles.ActionCreator), setRoleHoldersPermission, true); mpPolicy.setRolePermission(uint8(Roles.ActionCreator), setRolePermissionsPermission, true); mpPolicy.setRolePermission(uint8(Roles.ActionCreator), revokePoliciesPermission, true); mpPolicy.setRolePermission(uint8(Roles.ActionCreator), updateRoleDescriptionPerimssion, true); + mpPolicy.setRolePermission(uint8(Roles.ActionCreator), setStrategyLogicAuthorizationsPermission, true); + mpPolicy.setRolePermission(uint8(Roles.ActionCreator), setStrategyAuthorizationsPermission, true); + mpPolicy.setRolePermission(uint8(Roles.ActionCreator), setAccountLogicAuthorizationsPermission, true); + mpPolicy.setRolePermission(uint8(Roles.ActionCreator), setStrategyLogicAuthAndNewStrategiesPermission, true); + mpPolicy.setRolePermission(uint8(Roles.ActionCreator), setScriptAuthAndSetPermissionsPermission, true); + mpPolicy.setRolePermission(uint8(Roles.ActionCreator), createAccountAndSetRolePermissionsPermission, true); vm.stopPrank(); } @@ -175,11 +203,11 @@ contract LlamaGovernanceScriptTest is LlamaTestSetup { }); } - function _assumeInitializeRoles(RoleDescription[] memory descriptions) public { + function _assumeInitializeRoles(RoleDescription[] memory descriptions) public pure { vm.assume(descriptions.length < 247); // max unit8 (255) - total number of exisitng roles (8) } - function _assumeRoleHolders(RoleHolderData[] memory roleHolders) public { + function _assumeRoleHolders(RoleHolderData[] memory roleHolders) public view { vm.assume(roleHolders.length < 10); for (uint256 i = 0; i < roleHolders.length; i++) { // Cannot be 0 (all holders role) and cannot be greater than numRoles @@ -190,43 +218,43 @@ contract LlamaGovernanceScriptTest is LlamaTestSetup { } } - function _assumeStrategies(uint256 salt1, uint256 salt2, uint256 salt3) public { + function _assumeStrategies(uint256 salt1, uint256 salt2, uint256 salt3) public pure { vm.assume(salt1 != salt2 && salt1 != salt3 && salt2 != salt3); } - function _assumeUpdateRoleDescriptions(LlamaGovernanceScript.UpdateRoleDescription[] memory descriptions) internal { + function _assumeUpdateRoleDescriptions(LlamaGovernanceScript.UpdateRoleDescription[] memory descriptions) public pure { vm.assume(descriptions.length <= 9); //number of roles in the Roles enum for (uint256 i = 0; i < descriptions.length; i++) { descriptions[i].role = uint8(i); } } - function _boundRolePermissions(RolePermissionData[] memory rolePermissions) public { + function _boundRolePermissions(RolePermissionData[] memory rolePermissions) public view { for (uint256 i = 0; i < rolePermissions.length; i++) { // Cannot be 0 (all holders role) and cannot be greater than numRoles rolePermissions[i].role = uint8(bound(rolePermissions[i].role, 1, mpPolicy.numRoles())); } } - function _createAction(bytes memory data) internal returns (ActionInfo memory actionInfo, uint256 actionId) { + function _createAction(bytes memory data) internal returns (ActionInfo memory actionInfo) { vm.prank(actionCreatorAaron); - actionId = mpCore.createAction(uint8(Roles.ActionCreator), mpStrategy2, address(governanceScript), 0, data, ""); - actionInfo = ActionInfo( - actionId, actionCreatorAaron, uint8(Roles.ActionCreator), mpStrategy2, address(governanceScript), 0, data - ); + uint256 actionId = mpCore.createAction(uint8(Roles.ActionCreator), mpStrategy2, address(govScript), 0, data, ""); + actionInfo = + ActionInfo(actionId, actionCreatorAaron, uint8(Roles.ActionCreator), mpStrategy2, address(govScript), 0, data); vm.warp(block.timestamp + 1); _approveAction(actionInfo); } function _createStrategies(uint256 salt1, uint256 salt2, uint256 salt3, bool isFixedLengthApprovalPeriod) internal + view returns ( LlamaRelativeStrategyBase.Config[] memory newStrategies, LlamaGovernanceScript.CreateStrategies memory strategies ) { newStrategies = new LlamaRelativeStrategyBase.Config[](3); - ILlamaStrategy[] memory strategyAddresses = new ILlamaStrategy[](3); + // ILlamaStrategy[] memory strategyAddresses = new ILlamaStrategy[](3); newStrategies[0] = _createStrategy(salt1, isFixedLengthApprovalPeriod); newStrategies[1] = _createStrategy(salt2, isFixedLengthApprovalPeriod); @@ -330,13 +358,53 @@ contract Aggregate is LlamaGovernanceScriptTest { bytes memory data = abi.encodeWithSelector(AGGREGATE_SELECTOR, targets, calls); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectInitializeRolesEvents(descriptions); vm.expectEmit(); emit AccountCreated(accountAddresses[0], accountLogic, DeployUtils.encodeAccount(newAccounts[0])); mpCore.executeAction(actionInfo); } + + function test_RevertsIf_CallReverted(RoleDescription description) public { + targets.push(address(0)); + calls.push(abi.encodeWithSelector(LlamaPolicy.initializeRole.selector, description)); + + bytes memory data = abi.encodeWithSelector(AGGREGATE_SELECTOR, targets, calls); + + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectRevert(); + // CallReverted error cannot be reached because we get a "FailedActionExecution" error first. + mpCore.executeAction(actionInfo); + } + + function test_RevertsIf_UnauthorizedTarget(address target) public { + vm.assume(target != address(mpPolicy) && target != address(mpCore)); + targets.push(address(target)); + calls.push(abi.encodeWithSelector(LlamaPolicy.initializeRole.selector, "test")); + + bytes memory data = abi.encodeWithSelector(AGGREGATE_SELECTOR, targets, calls); + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectRevert(); + // UnauthorizedTarget error cannot be reached because we get a "FailedActionExecution" error first. + mpCore.executeAction(actionInfo); + } + + function test_RevertsIf_MismatchedArrayLength(address[] calldata _targets, uint8 length) public { + vm.assume(targets.length != length); + bytes[] memory _calls = new bytes[](length); + for (uint256 i = 0; i < length; i++) { + _calls[i] = abi.encodeWithSelector(LlamaPolicy.initializeRole.selector, "test"); + } + bytes memory data = abi.encodeWithSelector(AGGREGATE_SELECTOR, _targets, _calls); + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectRevert(); + // MismatchedArrayLength error cannot be reached because we get a "FailedActionExecution" error first. + mpCore.executeAction(actionInfo); + } } contract InitializeRolesAndSetRoleHolders is LlamaGovernanceScriptTest { @@ -347,9 +415,8 @@ contract InitializeRolesAndSetRoleHolders is LlamaGovernanceScriptTest { _assumeInitializeRoles(descriptions); _assumeRoleHolders(roleHolders); - bytes memory data = - abi.encodeWithSelector(INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR, descriptions, roleHolders); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + bytes memory data = abi.encodeWithSelector(INIT_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR, descriptions, roleHolders); + (ActionInfo memory actionInfo) = _createAction(data); _expectInitializeRolesEvents(descriptions); _expectRoleHolderEvents(roleHolders); mpCore.executeAction(actionInfo); @@ -367,7 +434,7 @@ contract InitializeRolesAndSetRolePermissions is LlamaGovernanceScriptTest { bytes memory data = abi.encodeWithSelector(INITIALIZE_ROLES_AND_SET_ROLE_PERMISSIONS_SELECTOR, descriptions, rolePermissions); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectInitializeRolesEvents(descriptions); _expectRolePermissionEvents(rolePermissions); mpCore.executeAction(actionInfo); @@ -393,12 +460,9 @@ contract InitializeRolesAndSetRoleHoldersAndSetRolePermissions is LlamaGovernanc }); bytes memory data = abi.encodeWithSelector( - INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_AND_SET_ROLE_PERMISSIONS_SELECTOR, - descriptions, - roleHolders, - rolePermissions + INIT_ROLES_AND_HOLDERS_AND_PERMISSIONS_SELECTOR, descriptions, roleHolders, rolePermissions ); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectInitializeRolesEvents(descriptions); _expectRoleHolderEvents(roleHolders); _expectRolePermissionEvents(rolePermissions); @@ -422,7 +486,7 @@ contract CreateNewStrategiesAndSetRoleHolders is LlamaGovernanceScriptTest { bytes memory data = abi.encodeWithSelector(CREATE_NEW_STRATEGIES_AND_SET_ROLE_HOLDERS_SELECTOR, strategies, roleHolders); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectCreateStrategiesEvents(newStrategies); _expectRoleHolderEvents(roleHolders); @@ -449,9 +513,9 @@ contract CreateNewStrategiesAndInitializeRolesAndSetRoleHolders is LlamaGovernan = _createStrategies(salt1, salt2, salt3, isFixedLengthApprovalPeriod); bytes memory data = abi.encodeWithSelector( - CREATE_NEW_STRATEGIES_AND_INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_SELECTOR, strategies, descriptions, roleHolders + CREATE_STRATEGIES_AND_INIT_ROLES_AND_HOLDERS_SELECTOR, strategies, descriptions, roleHolders ); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectCreateStrategiesEvents(newStrategies); _expectInitializeRolesEvents(descriptions); @@ -478,7 +542,7 @@ contract CreateNewStrategiesAndSetRolePermissions is LlamaGovernanceScriptTest { bytes memory data = abi.encodeWithSelector(CREATE_NEW_STRATEGIES_AND_SET_ROLE_PERMISSIONS_SELECTOR, strategies, rolePermissions); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectCreateStrategiesEvents(newStrategies); _expectRolePermissionEvents(rolePermissions); @@ -514,13 +578,9 @@ contract CreateNewStrategiesAndInitializeRolesAndSetRoleHoldersAndSetRolePermiss }); bytes memory data = abi.encodeWithSelector( - CREATE_NEW_STRATEGIES_AND_INITIALIZE_ROLES_AND_SET_ROLE_HOLDERS_AND_SET_ROLE_PERMISSIONS_SELECTOR, - strategies, - descriptions, - roleHolders, - rolePermissions + CREATE_STRATEGIES_WITH_ROLES_AND_PERMISSIONS_SELECTOR, strategies, descriptions, roleHolders, rolePermissions ); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectCreateStrategiesEvents(newStrategies); _expectInitializeRolesEvents(descriptions); @@ -540,7 +600,7 @@ contract RevokePoliciesAndUpdateRoleDescriptions is LlamaGovernanceScriptTest { bytes memory data = abi.encodeWithSelector(REVOKE_POLICIES_AND_UPDATE_ROLE_DESCRIPTIONS_SELECTOR, revokePolicies, descriptions); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); vm.expectEmit(); emit RoleAssigned(address(disapproverDave), uint8(Roles.Disapprover), 0, 0); @@ -550,8 +610,8 @@ contract RevokePoliciesAndUpdateRoleDescriptions is LlamaGovernanceScriptTest { } } -contract RevokePoliciesAndUpdateRoleDescriptionsAndSetRoleHolders is LlamaGovernanceScriptTest { - function test_RevokePoliciesAndUpdateRoleDescriptionsAndSetRoleHolders( +contract RevokePoliciesAndSetRoleDescsAndHolders is LlamaGovernanceScriptTest { + function test_RevokePoliciesAndSetRoleDescsAndHolders( LlamaGovernanceScript.UpdateRoleDescription[] memory descriptions ) public { revokePolicies.push(disapproverDave); @@ -567,12 +627,9 @@ contract RevokePoliciesAndUpdateRoleDescriptionsAndSetRoleHolders is LlamaGovern }); bytes memory data = abi.encodeWithSelector( - REVOKE_POLICIES_AND_UPDATE_ROLE_DESCRIPTIONS_AND_SET_ROLE_HOLDERS_SELECTOR, - revokePolicies, - descriptions, - roleHolders + REVOKE_POLICIES_AND_SET_ROLE_DESCS_AND_HOLDERS_SELECTOR, revokePolicies, descriptions, roleHolders ); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); vm.expectEmit(); emit RoleAssigned(address(disapproverDave), uint8(Roles.Disapprover), 0, 0); @@ -586,8 +643,8 @@ contract RevokePoliciesAndUpdateRoleDescriptionsAndSetRoleHolders is LlamaGovern contract InitializeRoles is LlamaGovernanceScriptTest { function testFuzz_initializeRoles(RoleDescription[] memory descriptions) public { _assumeInitializeRoles(descriptions); - bytes memory data = abi.encodeWithSelector(INITIALIZE_ROLES_SELECTOR, descriptions); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + bytes memory data = abi.encodeWithSelector(INIT_ROLES_SELECTOR, descriptions); + (ActionInfo memory actionInfo) = _createAction(data); _expectInitializeRolesEvents(descriptions); mpCore.executeAction(actionInfo); } @@ -597,7 +654,7 @@ contract SetRoleHolders is LlamaGovernanceScriptTest { function testFuzz_setRoleHolders(RoleHolderData[] memory roleHolders) public { _assumeRoleHolders(roleHolders); bytes memory data = abi.encodeWithSelector(SET_ROLE_HOLDERS_SELECTOR, roleHolders); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectRoleHolderEvents(roleHolders); mpCore.executeAction(actionInfo); } @@ -607,7 +664,7 @@ contract SetRolePermissions is LlamaGovernanceScriptTest { function testFuzz_setRolePermissions(RolePermissionData[] memory rolePermissions) public { _boundRolePermissions(rolePermissions); bytes memory data = abi.encodeWithSelector(SET_ROLE_PERMISSIONS_SELECTOR, rolePermissions); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectRolePermissionEvents(rolePermissions); mpCore.executeAction(actionInfo); } @@ -617,7 +674,7 @@ contract RevokePolicies is LlamaGovernanceScriptTest { function test_revokePolicies() public { revokePolicies.push(disapproverDave); bytes memory data = abi.encodeWithSelector(REVOKE_POLICIES_SELECTOR, revokePolicies); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); vm.expectEmit(); emit RoleAssigned(address(disapproverDave), uint8(Roles.Disapprover), 0, 0); mpCore.executeAction(actionInfo); @@ -630,9 +687,219 @@ contract UpdateRoleDescriptions is LlamaGovernanceScriptTest { { _assumeUpdateRoleDescriptions(roleDescriptions); bytes memory data = abi.encodeWithSelector(UPDATE_ROLE_DESCRIPTIONS_SELECTOR, roleDescriptions); - (ActionInfo memory actionInfo, uint256 actionId) = _createAction(data); + (ActionInfo memory actionInfo) = _createAction(data); _expectUpdateRoleDescriptionsEvents(roleDescriptions); mpCore.executeAction(actionInfo); } } + +contract SetStrategyLogicAuthorizations is LlamaGovernanceScriptTest { + function test_setStrategyLogicAuthorizations(bool authorized) public { + ILlamaStrategy[] memory strategies = new ILlamaStrategy[](3); + strategies[0] = relativeHolderQuorumLogic; + strategies[1] = absolutePeerReviewLogic; + strategies[2] = absoluteQuorumLogic; + + bytes memory data = + abi.encodeWithSelector(LlamaGovernanceScript.setStrategyLogicAuthorizations.selector, strategies, authorized); + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectEmit(); + emit StrategyLogicAuthorizationSet(relativeHolderQuorumLogic, authorized); + vm.expectEmit(); + emit StrategyLogicAuthorizationSet(absolutePeerReviewLogic, authorized); + vm.expectEmit(); + emit StrategyLogicAuthorizationSet(absoluteQuorumLogic, authorized); + + mpCore.executeAction(actionInfo); + } +} + +contract SetStrategyAuthorizations is LlamaGovernanceScriptTest { + function test_setStrategyAuthorizations(bool authorized) public { + ILlamaStrategy[] memory strategies = new ILlamaStrategy[](1); + strategies[0] = mpStrategy1; + + bytes memory data = + abi.encodeWithSelector(LlamaGovernanceScript.setStrategyAuthorizations.selector, strategies, authorized); + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectEmit(); + emit StrategyAuthorizationSet(mpStrategy1, authorized); + + mpCore.executeAction(actionInfo); + } +} + +contract SetAccountLogicAuthorizations is LlamaGovernanceScriptTest { + function test_SetAccountLogicAuthorizations(ILlamaAccount[] calldata accountLogics, bool authorized) public { + vm.assume(accountLogics.length < 5); + + bytes memory data = + abi.encodeWithSelector(LlamaGovernanceScript.setAccountLogicAuthorizations.selector, accountLogics, authorized); + (ActionInfo memory actionInfo) = _createAction(data); + + for (uint256 i = 0; i < accountLogics.length; i++) { + vm.expectEmit(); + emit AccountLogicAuthorizationSet(accountLogics[i], authorized); + } + + mpCore.executeAction(actionInfo); + } +} + +contract SetStrategyLogicAuthorizationAndCreateStrategies is LlamaGovernanceScriptTest { + function test_SetStrategyLogicAuthorizationAndCreateStrategies() public { + LlamaRelativeStrategyBase.Config[] memory newStrategies = new LlamaRelativeStrategyBase.Config[](1); + newStrategies[0] = LlamaRelativeStrategyBase.Config({ + approvalPeriod: 0, + queuingPeriod: 0, + expirationPeriod: 2 days, + isFixedLengthApprovalPeriod: false, + minApprovalPct: 0, + minDisapprovalPct: 10_001, + approvalRole: uint8(Roles.Approver), + disapprovalRole: uint8(Roles.Disapprover), + forceApprovalRoles: new uint8[](0), + forceDisapprovalRoles: new uint8[](0) + }); + ILlamaStrategy instantExecutionStrategy = lens.computeLlamaStrategyAddress( + address(relativeQuantityQuorumLogic), DeployUtils.encodeStrategy(newStrategies[0]), address(mpCore) + ); + bytes memory data = abi.encodeWithSelector( + LlamaGovernanceScript.setStrategyLogicAuthAndNewStrategies.selector, + relativeQuantityQuorumLogic, + DeployUtils.encodeStrategyConfigs(newStrategies) + ); + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectEmit(); + emit StrategyLogicAuthorizationSet(relativeQuantityQuorumLogic, true); + vm.expectEmit(); + emit StrategyCreated( + instantExecutionStrategy, relativeQuantityQuorumLogic, DeployUtils.encodeStrategy(newStrategies[0]) + ); + mpCore.executeAction(actionInfo); + } +} + +contract SetScriptAuthAndSetPermissions is LlamaGovernanceScriptTest { + function test_SetScriptAuthAndSetPermissions(address script, bool authorized, bytes4[] calldata selectors) public { + ILlamaStrategy[] memory strategies = new ILlamaStrategy[](selectors.length); + + bytes memory data = abi.encodeWithSelector( + LlamaGovernanceScript.setScriptAuthAndSetPermissions.selector, + script, + authorized, + uint8(Roles.ActionCreator), + selectors, + strategies + ); + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectEmit(); + emit ScriptAuthorizationSet(script, authorized); + for (uint256 i = 0; i < selectors.length; i++) { + PermissionData memory permissionData = PermissionData(script, selectors[i], strategies[i]); + bytes32 permissionId = lens.computePermissionId(permissionData); + vm.expectEmit(); + emit RolePermissionAssigned(uint8(Roles.ActionCreator), permissionId, permissionData, authorized); + } + mpCore.executeAction(actionInfo); + } +} + +contract CreateAccountAndSetRolePermissions is LlamaGovernanceScriptTest { + function test_CreateAccountAndSetRolePermissions() public { + bytes memory config = abi.encode(LlamaAccount.Config({name: "mockAccountERC20"})); + LlamaGovernanceScript.CreateAccounts memory account = LlamaGovernanceScript.CreateAccounts(accountLogic, config); + + ILlamaAccount accountAddress = lens.computeLlamaAccountAddress(address(accountLogic), config, address(mpCore)); + + PermissionData memory permissionData1 = + PermissionData(address(accountAddress), LlamaAccount.batchTransferNativeToken.selector, mpStrategy2); + PermissionData memory permissionData2 = + PermissionData(address(accountAddress), LlamaAccount.batchTransferERC20.selector, mpStrategy2); + PermissionData memory permissionData3 = + PermissionData(address(accountAddress), LlamaAccount.batchApproveERC20.selector, mpStrategy2); + PermissionData memory permissionData4 = + PermissionData(address(accountAddress), LlamaAccount.batchTransferERC721.selector, mpStrategy2); + PermissionData memory permissionData5 = + PermissionData(address(accountAddress), LlamaAccount.batchApproveERC721.selector, mpStrategy2); + PermissionData memory permissionData6 = + PermissionData(address(accountAddress), LlamaAccount.batchApproveOperatorERC721.selector, mpStrategy2); + + RolePermissionData[] memory _permissions = new RolePermissionData[](6); + _permissions[0] = RolePermissionData(uint8(Roles.ActionCreator), permissionData1, true); + _permissions[1] = RolePermissionData(uint8(Roles.ActionCreator), permissionData2, true); + _permissions[2] = RolePermissionData(uint8(Roles.ActionCreator), permissionData3, true); + _permissions[3] = RolePermissionData(uint8(Roles.ActionCreator), permissionData4, true); + _permissions[4] = RolePermissionData(uint8(Roles.ActionCreator), permissionData5, true); + _permissions[5] = RolePermissionData(uint8(Roles.ActionCreator), permissionData6, true); + + bytes memory data = + abi.encodeWithSelector(LlamaGovernanceScript.createAccountAndSetRolePermissions.selector, account, _permissions); + + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectEmit(); + emit AccountCreated(accountAddress, accountLogic, config); + + vm.expectEmit(); + emit RolePermissionAssigned( + uint8(Roles.ActionCreator), LlamaUtils.computePermissionId(permissionData1), permissionData1, true + ); + + vm.expectEmit(); + emit RolePermissionAssigned( + uint8(Roles.ActionCreator), LlamaUtils.computePermissionId(permissionData2), permissionData2, true + ); + + vm.expectEmit(); + emit RolePermissionAssigned( + uint8(Roles.ActionCreator), LlamaUtils.computePermissionId(permissionData3), permissionData3, true + ); + + vm.expectEmit(); + emit RolePermissionAssigned( + uint8(Roles.ActionCreator), LlamaUtils.computePermissionId(permissionData4), permissionData4, true + ); + + vm.expectEmit(); + emit RolePermissionAssigned( + uint8(Roles.ActionCreator), LlamaUtils.computePermissionId(permissionData5), permissionData5, true + ); + + vm.expectEmit(); + emit RolePermissionAssigned( + uint8(Roles.ActionCreator), LlamaUtils.computePermissionId(permissionData6), permissionData6, true + ); + + mpCore.executeAction(actionInfo); + } + + function test_RevertsIf_TargetIsNotAccount(address notAccount) public { + bytes memory config = abi.encode(LlamaAccount.Config({name: "mockAccountERC20"})); + LlamaGovernanceScript.CreateAccounts memory account = LlamaGovernanceScript.CreateAccounts(accountLogic, config); + + ILlamaAccount accountAddress = lens.computeLlamaAccountAddress(address(accountLogic), config, address(mpCore)); + + vm.assume(notAccount != address(accountAddress)); + + PermissionData memory permissionData = + PermissionData(notAccount, LlamaAccount.batchTransferNativeToken.selector, mpStrategy2); + + RolePermissionData[] memory _permissions = new RolePermissionData[](1); + _permissions[0] = RolePermissionData(uint8(Roles.ActionCreator), permissionData, true); + + bytes memory data = + abi.encodeWithSelector(LlamaGovernanceScript.createAccountAndSetRolePermissions.selector, account, _permissions); + + (ActionInfo memory actionInfo) = _createAction(data); + + vm.expectRevert(); // reverts with FailedActionExecution and does not reach the TargetIsNotAccount error + + mpCore.executeAction(actionInfo); + } +}