From f77d81efe4d1d6c6446f4185c13a6cb77ab0ed97 Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Mon, 1 Apr 2024 18:53:32 -0400 Subject: [PATCH 01/10] account execute guard --- src/guards/LlamaAccountExecuteGuard.sol | 112 ++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/guards/LlamaAccountExecuteGuard.sol diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol new file mode 100644 index 000000000..fa4053f19 --- /dev/null +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Initializable} from "@openzeppelin/proxy/utils/Initializable.sol"; + +import {ILlamaActionGuard} from "src/interfaces/ILlamaActionGuard.sol"; +import {LlamaUtils} from "src/lib/LlamaUtils.sol"; +import {ActionInfo} from "src/lib/Structs.sol"; + +/// @title Llama Account Execute Guard +/// @author Llama (devsdosomething@llama.xyz) +/// @notice A guard that only allows authorized targets to be called from a Llama Account. +/// @dev This guard should be used to protect the `execute` function in the `LlamaAccount` contract +contract LlamaAccountExecuteGuard is ILlamaActionGuard, Initializable { + // ========================= + // ======== Structs ======== + // ========================= + + /// @dev Llama account execute guard initialization configuration. + struct Config { + address executor; // The address of the `LlamaExecutor` contract. + AuthorizedTargetConfig[] authorizedTargets; // The authorized targets and their call type. + } + + /// @dev Authorized target configuration. + struct AuthorizedTargetConfig { + address target; // The target contract. + bool withDelegatecall; // Call type. + bool isAuthorized; // Is the target authorized. + } + + // ========================= + // ======== Errors ======== + // ========================= + + /// @dev Only callable by a Llama instance's executor. + error OnlyLlama(); + + /// @dev Thrown if the target with call type is not authorized. + error UnauthorizedTarget(address target, bool withDelegatecall); + + // ========================= + // ======== Events ======== + // ========================= + + /// @notice Emitted when a target with call type is authorized. + event TargetAuthorized(address indexed target, bool indexed withDelegatecall, bool isAuthorized); + + // =================================== + // ======== Storage Variables ======== + // =================================== + + /// @notice The Llama instance's executor. + address public llamaExecutor; + + /// @notice A mapping of authorized targets and their call type. + mapping(address target => mapping(bool withDelegatecall => bool isAuthorized)) public authorizedTargets; + + // ====================================================== + // ======== Contract Creation and Initialization ======== + // ====================================================== + + /// @dev This contract is deployed as a minimal proxy from the guard factory's `deploy` function. The + /// `_disableInitializers` locks the implementation (logic) contract, preventing any future initialization of it. + constructor() { + _disableInitializers(); + } + + /// @notice Initializes a new `LlamaAccountExecuteGuard` clone. + /// @dev This function is called by the `deploy` function in the `LlamaGuardFactory` contract. The `initializer` + /// modifier ensures that this function can be invoked at most once. + /// @param config The guard configuration, encoded as bytes to support differing constructor arguments in + /// different guard logic contracts. + function initialize(bytes memory config) external initializer { + Config memory guardConfig = abi.decode(config, (Config)); + llamaExecutor = guardConfig.executor; + _setAuthorizedTargets(guardConfig.authorizedTargets); + } + + // ================================ + // ======== External Logic ======== + // ================================ + + /// @inheritdoc ILlamaActionGuard + function validateActionCreation(ActionInfo calldata actionInfo) external view {} + + /// @notice Allows the llama executor to set the authorized targets and their call type. + /// @param data The data to set the authorized targets and their call type. + function setAuthorizedTargets(AuthorizedTargetConfig[] memory data) external { + if (msg.sender != llamaExecutor) revert OnlyLlama(); + _setAuthorizedTargets(data); + } + + /// @inheritdoc ILlamaActionGuard + function validatePreActionExecution(ActionInfo calldata actionInfo) external pure {} + + /// @inheritdoc ILlamaActionGuard + function validatePostActionExecution(ActionInfo calldata actionInfo) external pure {} + + // ================================ + // ======== Internal Logic ======== + // ================================ + + /// @dev Sets the authorized targets and their call type. + function _setAuthorizedTargets(AuthorizedTargetConfig[] memory data) internal { + uint256 length = data.length; + for (uint256 i = 0; i < length; LlamaUtils.uncheckedIncrement(i)) { + authorizedTargets[data[i].target][data[i].withDelegatecall] = data[i].isAuthorized; + emit TargetAuthorized(data[i].target, data[i].withDelegatecall, data[i].isAuthorized); + } + } +} From 536ed7033df288b3077026648f5bd23101d80aff Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Mon, 1 Apr 2024 19:40:53 -0400 Subject: [PATCH 02/10] validateActionCreation --- src/guards/LlamaAccountExecuteGuard.sol | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol index fa4053f19..bea6d386e 100644 --- a/src/guards/LlamaAccountExecuteGuard.sol +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -82,7 +82,10 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuard, Initializable { // ================================ /// @inheritdoc ILlamaActionGuard - function validateActionCreation(ActionInfo calldata actionInfo) external view {} + function validateActionCreation(ActionInfo calldata actionInfo) external view { + (address target, bool withDelegatecall,,) = abi.decode(actionInfo.data, (address, bool, uint256, bytes)); + if (!authorizedTargets[target][withDelegatecall]) revert UnauthorizedTarget(target, withDelegatecall); + } /// @notice Allows the llama executor to set the authorized targets and their call type. /// @param data The data to set the authorized targets and their call type. From e0688f1e85d9a5eec9b51af5c58f291e382f293b Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Mon, 1 Apr 2024 21:11:10 -0400 Subject: [PATCH 03/10] working --- src/guards/LlamaAccountExecuteGuard.sol | 14 +++-- src/guards/LlamaActionGuardFactory.sol | 53 +++++++++++++++++++ .../ILlamaActionGuardMinimalProxy.sol | 18 +++++++ 3 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/guards/LlamaActionGuardFactory.sol create mode 100644 src/interfaces/ILlamaActionGuardMinimalProxy.sol diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol index bea6d386e..b97883a66 100644 --- a/src/guards/LlamaAccountExecuteGuard.sol +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -3,7 +3,8 @@ pragma solidity 0.8.19; import {Initializable} from "@openzeppelin/proxy/utils/Initializable.sol"; -import {ILlamaActionGuard} from "src/interfaces/ILlamaActionGuard.sol"; +import {ILlamaActionGuardMinimalProxy} from "src/interfaces/ILlamaActionGuardMinimalProxy.sol"; +import {ILlamaActionGuard} from "./../interfaces/ILlamaActionGuard.sol"; import {LlamaUtils} from "src/lib/LlamaUtils.sol"; import {ActionInfo} from "src/lib/Structs.sol"; @@ -11,7 +12,7 @@ import {ActionInfo} from "src/lib/Structs.sol"; /// @author Llama (devsdosomething@llama.xyz) /// @notice A guard that only allows authorized targets to be called from a Llama Account. /// @dev This guard should be used to protect the `execute` function in the `LlamaAccount` contract -contract LlamaAccountExecuteGuard is ILlamaActionGuard, Initializable { +contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializable { // ========================= // ======== Structs ======== // ========================= @@ -66,15 +67,12 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuard, Initializable { _disableInitializers(); } - /// @notice Initializes a new `LlamaAccountExecuteGuard` clone. - /// @dev This function is called by the `deploy` function in the `LlamaGuardFactory` contract. The `initializer` - /// modifier ensures that this function can be invoked at most once. - /// @param config The guard configuration, encoded as bytes to support differing constructor arguments in - /// different guard logic contracts. - function initialize(bytes memory config) external initializer { + /// @inheritdoc ILlamaActionGuardMinimalProxy + function initialize(bytes memory config) external initializer returns (bool) { Config memory guardConfig = abi.decode(config, (Config)); llamaExecutor = guardConfig.executor; _setAuthorizedTargets(guardConfig.authorizedTargets); + return true; } // ================================ diff --git a/src/guards/LlamaActionGuardFactory.sol b/src/guards/LlamaActionGuardFactory.sol new file mode 100644 index 000000000..3efd03abd --- /dev/null +++ b/src/guards/LlamaActionGuardFactory.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {Clones} from "@openzeppelin/proxy/Clones.sol"; + +import {ILlamaActionGuardMinimalProxy} from "src/interfaces/ILlamaActionGuardMinimalProxy.sol"; + +/// @title LlamaActionGuardFactory +/// @author Llama (devsdosomething@llama.xyz) +/// @notice This contract enables Llama instances to deploy action guards. +contract LlamaActionGuardFactory { + /// @dev Configuration of new Llama action guard. + struct LlamaActionGuardConfig { + ILlamaActionGuardMinimalProxy actionGuardLogic; // The logic contract of the new action guard. + bytes initializationData; // The initialization data for the new action guard. + uint256 nonce; // The nonce of the new action guard. + } + + /// @dev Emitted when a new Llama action guard is created. + event LlamaActionGuardCreated( + address indexed deployer, + ILlamaActionGuardMinimalProxy indexed actionGuardLogic, + ILlamaActionGuardMinimalProxy actionGuard, + bytes initializationData, + uint256 nonce, + uint256 chainId + ); + + /// @notice Deploys a new Llama action guard. + /// @param actionGuardConfig The configuration of the new Llama action guard. + /// @return actionGuard The address of the new action guard. + function deploy(LlamaActionGuardConfig memory actionGuardConfig) + external + returns (ILlamaActionGuardMinimalProxy actionGuard) + { + bytes32 salt = + keccak256(abi.encodePacked(msg.sender, actionGuardConfig.initializationData, actionGuardConfig.nonce)); + + // Deploy and initialize Llama action guard + actionGuard = + ILlamaActionGuardMinimalProxy(Clones.cloneDeterministic(address(actionGuardConfig.actionGuardLogic), salt)); + actionGuard.initialize(actionGuardConfig.initializationData); + + emit LlamaActionGuardCreated( + msg.sender, + actionGuardConfig.actionGuardLogic, + actionGuard, + actionGuardConfig.initializationData, + actionGuardConfig.nonce, + block.chainid + ); + } +} diff --git a/src/interfaces/ILlamaActionGuardMinimalProxy.sol b/src/interfaces/ILlamaActionGuardMinimalProxy.sol new file mode 100644 index 000000000..2feda812d --- /dev/null +++ b/src/interfaces/ILlamaActionGuardMinimalProxy.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; + +import {ILlamaActionGuard} from "src/interfaces/ILlamaActionGuard.sol"; + +/// @title Llama Action Guard Minimal Proxy Interface +/// @author Llama (devsdosomething@llama.xyz) +/// @notice This is the interface for minimal proxy action guards. +interface ILlamaActionGuardMinimalProxy is ILlamaActionGuard { + /// @notice Initializes a new clone of the action guard. + /// @dev This function is called by the `deploy` function in the `LlamaActionGuardFactory` contract. The `initializer` + /// modifier ensures that this function can be invoked at most once. + /// @param config The guard configuration, encoded as bytes to support differing constructor arguments in + /// different guard logic contracts. + /// @return This return statement must be hardcoded to `true` to ensure that initializing an EOA + /// (like the zero address) will revert. + function initialize(bytes memory config) external returns (bool); +} From b04739a53146f3d5903227ea23f723f6afa4d3bc Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Mon, 1 Apr 2024 21:25:33 -0400 Subject: [PATCH 04/10] refactor --- src/guards/LlamaAccountExecuteGuard.sol | 5 ++--- src/guards/LlamaActionGuardFactory.sol | 8 +++++--- src/interfaces/ILlamaActionGuardMinimalProxy.sol | 3 ++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol index b97883a66..5f3fecc6e 100644 --- a/src/guards/LlamaAccountExecuteGuard.sol +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -19,7 +19,6 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializabl /// @dev Llama account execute guard initialization configuration. struct Config { - address executor; // The address of the `LlamaExecutor` contract. AuthorizedTargetConfig[] authorizedTargets; // The authorized targets and their call type. } @@ -68,9 +67,9 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializabl } /// @inheritdoc ILlamaActionGuardMinimalProxy - function initialize(bytes memory config) external initializer returns (bool) { + function initialize(address _llamaExecutor, bytes memory config) external initializer returns (bool) { + llamaExecutor = _llamaExecutor; Config memory guardConfig = abi.decode(config, (Config)); - llamaExecutor = guardConfig.executor; _setAuthorizedTargets(guardConfig.authorizedTargets); return true; } diff --git a/src/guards/LlamaActionGuardFactory.sol b/src/guards/LlamaActionGuardFactory.sol index 3efd03abd..480a2747e 100644 --- a/src/guards/LlamaActionGuardFactory.sol +++ b/src/guards/LlamaActionGuardFactory.sol @@ -11,6 +11,7 @@ import {ILlamaActionGuardMinimalProxy} from "src/interfaces/ILlamaActionGuardMin contract LlamaActionGuardFactory { /// @dev Configuration of new Llama action guard. struct LlamaActionGuardConfig { + address llamaExecutor; // The address of the Llama executor. ILlamaActionGuardMinimalProxy actionGuardLogic; // The logic contract of the new action guard. bytes initializationData; // The initialization data for the new action guard. uint256 nonce; // The nonce of the new action guard. @@ -19,6 +20,7 @@ contract LlamaActionGuardFactory { /// @dev Emitted when a new Llama action guard is created. event LlamaActionGuardCreated( address indexed deployer, + address indexed llamaExecutor, ILlamaActionGuardMinimalProxy indexed actionGuardLogic, ILlamaActionGuardMinimalProxy actionGuard, bytes initializationData, @@ -33,16 +35,16 @@ contract LlamaActionGuardFactory { external returns (ILlamaActionGuardMinimalProxy actionGuard) { - bytes32 salt = - keccak256(abi.encodePacked(msg.sender, actionGuardConfig.initializationData, actionGuardConfig.nonce)); + bytes32 salt = keccak256(abi.encodePacked(msg.sender, actionGuardConfig.llamaExecutor, actionGuardConfig.nonce)); // Deploy and initialize Llama action guard actionGuard = ILlamaActionGuardMinimalProxy(Clones.cloneDeterministic(address(actionGuardConfig.actionGuardLogic), salt)); - actionGuard.initialize(actionGuardConfig.initializationData); + actionGuard.initialize(actionGuardConfig.llamaExecutor, actionGuardConfig.initializationData); emit LlamaActionGuardCreated( msg.sender, + actionGuardConfig.llamaExecutor, actionGuardConfig.actionGuardLogic, actionGuard, actionGuardConfig.initializationData, diff --git a/src/interfaces/ILlamaActionGuardMinimalProxy.sol b/src/interfaces/ILlamaActionGuardMinimalProxy.sol index 2feda812d..deecb3e11 100644 --- a/src/interfaces/ILlamaActionGuardMinimalProxy.sol +++ b/src/interfaces/ILlamaActionGuardMinimalProxy.sol @@ -10,9 +10,10 @@ interface ILlamaActionGuardMinimalProxy is ILlamaActionGuard { /// @notice Initializes a new clone of the action guard. /// @dev This function is called by the `deploy` function in the `LlamaActionGuardFactory` contract. The `initializer` /// modifier ensures that this function can be invoked at most once. + /// @param llamaExecutor The address of the Llama executor. /// @param config The guard configuration, encoded as bytes to support differing constructor arguments in /// different guard logic contracts. /// @return This return statement must be hardcoded to `true` to ensure that initializing an EOA /// (like the zero address) will revert. - function initialize(bytes memory config) external returns (bool); + function initialize(address llamaExecutor, bytes memory config) external returns (bool); } From 4530f62176b980a4c83c7ef7241a8aee32e8d1ae Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Mon, 1 Apr 2024 21:32:03 -0400 Subject: [PATCH 05/10] fix --- src/guards/LlamaAccountExecuteGuard.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol index 5f3fecc6e..ad5840882 100644 --- a/src/guards/LlamaAccountExecuteGuard.sol +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -80,7 +80,8 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializabl /// @inheritdoc ILlamaActionGuard function validateActionCreation(ActionInfo calldata actionInfo) external view { - (address target, bool withDelegatecall,,) = abi.decode(actionInfo.data, (address, bool, uint256, bytes)); + // Decode the action calldata to get the LlamaAccount execute target and call type. + (address target, bool withDelegatecall,,) = abi.decode(actionInfo.data[4:], (address, bool, uint256, bytes)); if (!authorizedTargets[target][withDelegatecall]) revert UnauthorizedTarget(target, withDelegatecall); } From 96d57019e91b6b82a3914b4a04c26803f5d3e162 Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Mon, 1 Apr 2024 21:34:58 -0400 Subject: [PATCH 06/10] natspec --- src/guards/LlamaAccountExecuteGuard.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol index ad5840882..9e6cb4faa 100644 --- a/src/guards/LlamaAccountExecuteGuard.sol +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -10,7 +10,7 @@ import {ActionInfo} from "src/lib/Structs.sol"; /// @title Llama Account Execute Guard /// @author Llama (devsdosomething@llama.xyz) -/// @notice A guard that only allows authorized targets to be called from a Llama Account. +/// @notice A guard that only allows authorized targets to be called from a Llama account's execute function. /// @dev This guard should be used to protect the `execute` function in the `LlamaAccount` contract contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializable { // ========================= From 36d9cc00ad73dcf00566af7933be7ccc2c95831f Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Mon, 1 Apr 2024 21:56:13 -0400 Subject: [PATCH 07/10] script --- script/DeployLlamaFactory.s.sol | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/script/DeployLlamaFactory.s.sol b/script/DeployLlamaFactory.s.sol index 0c293e9ea..dba99d473 100644 --- a/script/DeployLlamaFactory.s.sol +++ b/script/DeployLlamaFactory.s.sol @@ -5,6 +5,8 @@ import {Script, stdJson} from "forge-std/Script.sol"; import {LlamaAccount} from "src/accounts/LlamaAccount.sol"; import {LlamaAccountWithDelegation} from "src/accounts/LlamaAccountWithDelegation.sol"; +import {LlamaAccountExecuteGuard} from "src/guards/LlamaAccountExecuteGuard.sol"; +import {LlamaActionGuardFactory} from "src/guards/LlamaActionGuardFactory.sol"; import {LlamaCore} from "src/LlamaCore.sol"; import {LlamaFactory} from "src/LlamaFactory.sol"; import {LlamaLens} from "src/LlamaLens.sol"; @@ -33,9 +35,11 @@ contract DeployLlamaFactory is Script { LlamaAccountWithDelegation accountWithDelegationLogic; LlamaPolicy policyLogic; LlamaPolicyMetadata policyMetadataLogic; + LlamaAccountExecuteGuard accountExecuteGuardLogic; // Factory and lens contracts. LlamaFactory factory; + LlamaActionGuardFactory actionGuardFactory; LlamaLens lens; // Llama scripts @@ -141,5 +145,17 @@ contract DeployLlamaFactory is Script { DeployUtils.print( string.concat(" LlamaAccountTokenDelegationScript:", vm.toString(address(accountTokenDelegationScript))) ); + + vm.broadcast(); + (success,) = msg.sender.call(""); + DeployUtils.print(string.concat(" Self call succeeded? ", vm.toString(success))); + + vm.broadcast(); + actionGuardFactory = new LlamaActionGuardFactory(); + DeployUtils.print(string.concat(" LlamaActionGuardFactory:", vm.toString(address(actionGuardFactory)))); + + vm.broadcast(); + accountExecuteGuardLogic = new LlamaAccountExecuteGuard(); + DeployUtils.print(string.concat(" LlamaAccountExecuteGuardLogic:", vm.toString(address(accountExecuteGuardLogic)))); } } From acb1b65817d50513282b9fbec0e1c62719f193d3 Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Wed, 3 Apr 2024 14:33:17 -0400 Subject: [PATCH 08/10] fix --- src/guards/LlamaAccountExecuteGuard.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol index 9e6cb4faa..4c2769907 100644 --- a/src/guards/LlamaAccountExecuteGuard.sol +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {Initializable} from "@openzeppelin/proxy/utils/Initializable.sol"; import {ILlamaActionGuardMinimalProxy} from "src/interfaces/ILlamaActionGuardMinimalProxy.sol"; -import {ILlamaActionGuard} from "./../interfaces/ILlamaActionGuard.sol"; +import {ILlamaActionGuard} from "src/interfaces/ILlamaActionGuard.sol"; import {LlamaUtils} from "src/lib/LlamaUtils.sol"; import {ActionInfo} from "src/lib/Structs.sol"; From 60c1778ccd1db7b913339159f8ddf11cfd8ea40b Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Wed, 3 Apr 2024 14:34:41 -0400 Subject: [PATCH 09/10] reorder --- src/guards/LlamaAccountExecuteGuard.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol index 4c2769907..84538066f 100644 --- a/src/guards/LlamaAccountExecuteGuard.sol +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -17,11 +17,6 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializabl // ======== Structs ======== // ========================= - /// @dev Llama account execute guard initialization configuration. - struct Config { - AuthorizedTargetConfig[] authorizedTargets; // The authorized targets and their call type. - } - /// @dev Authorized target configuration. struct AuthorizedTargetConfig { address target; // The target contract. @@ -29,6 +24,11 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializabl bool isAuthorized; // Is the target authorized. } + /// @dev Llama account execute guard initialization configuration. + struct Config { + AuthorizedTargetConfig[] authorizedTargets; // The authorized targets and their call type. + } + // ========================= // ======== Errors ======== // ========================= From b4412bba5c69dafc130812929dfe1ab54e7dc6c4 Mon Sep 17 00:00:00 2001 From: Rajath Alex Date: Wed, 3 Apr 2024 16:03:44 -0400 Subject: [PATCH 10/10] name --- src/guards/LlamaAccountExecuteGuard.sol | 10 ++++++- src/guards/LlamaActionGuardFactory.sol | 27 +++++++++++-------- .../ILlamaActionGuardMinimalProxy.sol | 3 ++- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/guards/LlamaAccountExecuteGuard.sol b/src/guards/LlamaAccountExecuteGuard.sol index 84538066f..fa73c2bd2 100644 --- a/src/guards/LlamaAccountExecuteGuard.sol +++ b/src/guards/LlamaAccountExecuteGuard.sol @@ -50,6 +50,9 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializabl // ======== Storage Variables ======== // =================================== + /// @notice Name of this action guard. + string public name; + /// @notice The Llama instance's executor. address public llamaExecutor; @@ -67,7 +70,12 @@ contract LlamaAccountExecuteGuard is ILlamaActionGuardMinimalProxy, Initializabl } /// @inheritdoc ILlamaActionGuardMinimalProxy - function initialize(address _llamaExecutor, bytes memory config) external initializer returns (bool) { + function initialize(string memory _name, address _llamaExecutor, bytes memory config) + external + initializer + returns (bool) + { + name = _name; llamaExecutor = _llamaExecutor; Config memory guardConfig = abi.decode(config, (Config)); _setAuthorizedTargets(guardConfig.authorizedTargets); diff --git a/src/guards/LlamaActionGuardFactory.sol b/src/guards/LlamaActionGuardFactory.sol index 480a2747e..3f811dd33 100644 --- a/src/guards/LlamaActionGuardFactory.sol +++ b/src/guards/LlamaActionGuardFactory.sol @@ -11,21 +11,22 @@ import {ILlamaActionGuardMinimalProxy} from "src/interfaces/ILlamaActionGuardMin contract LlamaActionGuardFactory { /// @dev Configuration of new Llama action guard. struct LlamaActionGuardConfig { + string name; // The name of the new action guard. address llamaExecutor; // The address of the Llama executor. + uint256 nonce; // The nonce of the new action guard. ILlamaActionGuardMinimalProxy actionGuardLogic; // The logic contract of the new action guard. bytes initializationData; // The initialization data for the new action guard. - uint256 nonce; // The nonce of the new action guard. } /// @dev Emitted when a new Llama action guard is created. event LlamaActionGuardCreated( address indexed deployer, + string name, address indexed llamaExecutor, - ILlamaActionGuardMinimalProxy indexed actionGuardLogic, - ILlamaActionGuardMinimalProxy actionGuard, - bytes initializationData, uint256 nonce, - uint256 chainId + ILlamaActionGuardMinimalProxy actionGuard, + ILlamaActionGuardMinimalProxy indexed actionGuardLogic, + bytes initializationData ); /// @notice Deploys a new Llama action guard. @@ -35,21 +36,25 @@ contract LlamaActionGuardFactory { external returns (ILlamaActionGuardMinimalProxy actionGuard) { - bytes32 salt = keccak256(abi.encodePacked(msg.sender, actionGuardConfig.llamaExecutor, actionGuardConfig.nonce)); + bytes32 salt = keccak256( + abi.encodePacked(msg.sender, actionGuardConfig.name, actionGuardConfig.llamaExecutor, actionGuardConfig.nonce) + ); // Deploy and initialize Llama action guard actionGuard = ILlamaActionGuardMinimalProxy(Clones.cloneDeterministic(address(actionGuardConfig.actionGuardLogic), salt)); - actionGuard.initialize(actionGuardConfig.llamaExecutor, actionGuardConfig.initializationData); + actionGuard.initialize( + actionGuardConfig.name, actionGuardConfig.llamaExecutor, actionGuardConfig.initializationData + ); emit LlamaActionGuardCreated( msg.sender, + actionGuardConfig.name, actionGuardConfig.llamaExecutor, - actionGuardConfig.actionGuardLogic, - actionGuard, - actionGuardConfig.initializationData, actionGuardConfig.nonce, - block.chainid + actionGuard, + actionGuardConfig.actionGuardLogic, + actionGuardConfig.initializationData ); } } diff --git a/src/interfaces/ILlamaActionGuardMinimalProxy.sol b/src/interfaces/ILlamaActionGuardMinimalProxy.sol index deecb3e11..12734083e 100644 --- a/src/interfaces/ILlamaActionGuardMinimalProxy.sol +++ b/src/interfaces/ILlamaActionGuardMinimalProxy.sol @@ -10,10 +10,11 @@ interface ILlamaActionGuardMinimalProxy is ILlamaActionGuard { /// @notice Initializes a new clone of the action guard. /// @dev This function is called by the `deploy` function in the `LlamaActionGuardFactory` contract. The `initializer` /// modifier ensures that this function can be invoked at most once. + /// @param name The name of the new action guard. /// @param llamaExecutor The address of the Llama executor. /// @param config The guard configuration, encoded as bytes to support differing constructor arguments in /// different guard logic contracts. /// @return This return statement must be hardcoded to `true` to ensure that initializing an EOA /// (like the zero address) will revert. - function initialize(address llamaExecutor, bytes memory config) external returns (bool); + function initialize(string memory name, address llamaExecutor, bytes memory config) external returns (bool); }