From 49f4c13aa2633ca4203740a22aec0784eb8af4d6 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Thu, 4 Jul 2024 20:48:53 -0700 Subject: [PATCH 1/4] Remove `executeDelegatedAction` and introduce 7579-style execution --- ERCS/erc-7710.md | 88 ++++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/ERCS/erc-7710.md b/ERCS/erc-7710.md index b4b1b5ea2a..96c437beaf 100644 --- a/ERCS/erc-7710.md +++ b/ERCS/erc-7710.md @@ -2,21 +2,22 @@ eip: 7710 title: Smart Contract Delegation Interfaces description: Minimal interfaces to enable smart contracts to consistently delegate capabilities to other contracts or EOAs. -author: Ryan McPeck (@McOso), Dan Finlay (@DanFinlay), Rob Dawson (@rojotek) +author: Ryan McPeck (@McOso), Dan Finlay (@DanFinlay), Rob Dawson (@rojotek), Derek Chiang (@derekchiang) discussions-to: https://ethereum-magicians.org/t/towards-more-conversational-wallet-connections-a-proposal-for-the-redeemdelegation-interface/16690 status: Draft type: Standards Track category: ERC created: 2024-05-20 -requires: 1271 +requires: 1271, 7579 --- ## Abstract -This proposal defines interfaces for smart contracts to delegate capabilities to other smart contracts, -smart contract accounts, or Externally Owned Accounts (EOAs). The delegating contract MUST -implement [ERC-1271](./eip-1271.md) along with the `IDelegator` interface. This framework empowers a -delegating contract with the ability to delegate any actions it has the authority to perform, +This proposal introduces a standard way for smart contracts to delegate capabilities to other smart contracts +or Externally Owned Accounts (EOAs). The delegating contract (delegator) must implement [ERC-1271](./eip-1271.md), +and must be able to authorize a `DelegationManager` contract to call the delegator to execute the desired action. + +This framework empowers a delegating contract with the ability to delegate any actions it has the authority to perform, thereby enabling more flexible and scalable contract interactions. This standard outlines the minimal interface necessary to facilitate such delegation. @@ -70,7 +71,7 @@ Delegator which executes the specified capability on behalf of the Delegator. flowchart LR redeemer(["redeemer"]) --"redeemDelegation"--> Delegation_Manager(["Delegation Manager"]) Delegation_Manager -.->|validate delegation w/ Action| Delegation_Manager - Delegation_Manager --"executeDelegatedAction"--> Delegator(["Delegator"]) + Delegation_Manager --"execute delegated action"--> Delegator(["Delegator"]) Delegator --"executes CALL using Action"--> Target(["Target"]) classDef action stroke:#333,stroke-width:2px,stroke-dasharray: 5, 5; @@ -80,52 +81,31 @@ flowchart LR ### Interfaces -#### `ERC7710.sol` +#### `ERC7710Manager.sol` -To comply with this standard, a smart contract MUST implement this execution -interface to become a Delegator. +The Delegation Manager MUST implement the `redeemDelegation` which will be responsible for validating the delegation +being invoked, and will then call the delegator to execute the action. -The `executeDelegatedAction` function SHOULD only allow calls from an approved Delegation Manager. +The bytes `_authority` passed in as a parameter to the `redeemDelegation` function contains the authority to execute a +specific action on behalf of the delegating contract. + +The `Action` struct has two fields: `mode` and `executionCalldata`, which are defined precisely as in ERC-7579 (under the "Execution Behavior" section). Briefly, `mode` encodes the "behavior" of the execution, which could be a single call, a batch call, a delegatecall, and others. `executionCallData` encodes the data of the execution, which typically includes at least a `target`, a `value`, and a `to` address. + +Briefly, `mode` encodes ```solidity pragma solidity 0.8.23; + /** - * @notice Action struct is a basic Call struct. * @title Action * @notice This struct represents an action to be taken. - * @dev It only includes the functional part of a transaction, allowing it to be - * agnostic whether this was sent from a protocol-level tx or UserOperation. + * @dev `mode` and `executionCalldata` are as defined in ERC-7579. */ struct Action { - address to; - uint256 value; - bytes data; + bytes32 mode; + bytes calldata executionCalldata; } -/** - * @title ERC7710 - * @notice Interface for a Delegator that exposes the minimal functionality required. - */ -interface ERC7710 is IERC1271 { - /** - * @notice executes a CALL using the data provided in the action - * @dev SHOULD enforce calls coming from an approved DelegationManager address - * @param _action the onchain action to perform - */ - function executeDelegatedAction(Action calldata _action) external; -} -``` - -#### `ERC7710Manager.sol` - -The Delegation Manager MUST implement the `redeemDelegation` which will be responsible for validating the delegation -being invoked, and will then call the `executeDelegatedAction` on the delegating contract. - -The bytes `_data` passed in as a parameter to the `redeemDelegation` function contains the authority to execute a -specific action on behalf of the delegating contract. - -```solidity -pragma solidity 0.8.23; /** * @title ERC7710Manager * @notice Interface for Delegation Manager that exposes the redeemDelegation function. @@ -133,11 +113,11 @@ pragma solidity 0.8.23; interface ERC7710Manager { /** * @notice This method validates the provided data and executes the action if the caller has authority to do so. - * @dev the structure of the _data bytes is determined by the specific Delegation Manager implementation - * @param _data the data used to validate the authority given to execute the action. + * @dev the structure of the _authority bytes is determined by the specific Delegation Manager implementation + * @param _authority the data used to validate the authority given to execute the action. * @param _action the action to be executed */ - function redeemDelegation(bytes calldata _data, Action calldata _action) external; + function redeemDelegation(bytes calldata _authority, Action calldata _action) external; } ``` @@ -165,6 +145,26 @@ enhancing the overall user experience. This ERC represents a step towards a more interconnected and flexible Ethereum ecosystem, where smart contracts can more effectively collaborate and adapt to users' needs. +### Execution Interface + +A previous iteration of this spec defined `Action` as a simple `(target, value, data)` tuple, and defined a specific +execution interface on the delegator that is `executeDelegatedAction(Action _action)` which the Delegation Manager is +supposed to call. + +That approach had a few downsides: + +- Existing smart accounts won't be compatible with this spec (unless they happen to implement the execution interface). +- The execution behavior is limited to a single call, since `Action` could only encode a single call. It made complex + execution behaviors such as batching, delegatecall, and CREATE2 impossible. + +To solve the first issue, we decided to remove the requirement for the delegator to implement any specific interface. +Rather, we rely on the Delegation Manager to correctly call the delegator, and we rely on the fact that a delegator would +only create `_authority` for a Delegation Manager that knows how to correctly call it. + +To solve the second issue, we decied to adopt the execution interface from ERC-7579, which had to solve a similar problem +within the context of modular smart accounts: defining a standardized execution interface that can support many types of +executions. + ## Security Considerations The introduction of customizable authorization terms requires careful consideration of how authorization data is From 28ae54a2e39007a29186011b8b1e0d7bfd0ad0a3 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Thu, 4 Jul 2024 20:50:24 -0700 Subject: [PATCH 2/4] Fix a few mistakes --- ERCS/erc-7710.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ERCS/erc-7710.md b/ERCS/erc-7710.md index 96c437beaf..e8084e89d7 100644 --- a/ERCS/erc-7710.md +++ b/ERCS/erc-7710.md @@ -91,8 +91,6 @@ specific action on behalf of the delegating contract. The `Action` struct has two fields: `mode` and `executionCalldata`, which are defined precisely as in ERC-7579 (under the "Execution Behavior" section). Briefly, `mode` encodes the "behavior" of the execution, which could be a single call, a batch call, a delegatecall, and others. `executionCallData` encodes the data of the execution, which typically includes at least a `target`, a `value`, and a `to` address. -Briefly, `mode` encodes - ```solidity pragma solidity 0.8.23; @@ -103,7 +101,7 @@ pragma solidity 0.8.23; */ struct Action { bytes32 mode; - bytes calldata executionCalldata; + bytes executionCalldata; } /** From 6fa941c01062ced07c0eaf07c9a2a8f5599833b7 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Wed, 17 Jul 2024 19:17:21 -0700 Subject: [PATCH 3/4] Remove the 7579 execution interface and use simple batching instead --- ERCS/erc-7710.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ERCS/erc-7710.md b/ERCS/erc-7710.md index e8084e89d7..b54b6e60cf 100644 --- a/ERCS/erc-7710.md +++ b/ERCS/erc-7710.md @@ -8,7 +8,7 @@ status: Draft type: Standards Track category: ERC created: 2024-05-20 -requires: 1271, 7579 +requires: 1271 --- ## Abstract @@ -70,9 +70,9 @@ Delegator which executes the specified capability on behalf of the Delegator. ```mermaid flowchart LR redeemer(["redeemer"]) --"redeemDelegation"--> Delegation_Manager(["Delegation Manager"]) - Delegation_Manager -.->|validate delegation w/ Action| Delegation_Manager - Delegation_Manager --"execute delegated action"--> Delegator(["Delegator"]) - Delegator --"executes CALL using Action"--> Target(["Target"]) + Delegation_Manager -.->|validate delegation w/ actions| Delegation_Manager + Delegation_Manager --"execute delegated actions"--> Delegator(["Delegator"]) + Delegator --"executes CALLs using actions"--> Target(["Target"]) classDef action stroke:#333,stroke-width:2px,stroke-dasharray: 5, 5; classDef entity fill:#af,stroke:#333,stroke-width:2px; @@ -84,24 +84,26 @@ flowchart LR #### `ERC7710Manager.sol` The Delegation Manager MUST implement the `redeemDelegation` which will be responsible for validating the delegation -being invoked, and will then call the delegator to execute the action. +being invoked, and will then call the delegator to execute a call for each action in the `_actions` array. If any + call in the array fails, `redeemDelegation` MUST revert. The bytes `_authority` passed in as a parameter to the `redeemDelegation` function contains the authority to execute a specific action on behalf of the delegating contract. -The `Action` struct has two fields: `mode` and `executionCalldata`, which are defined precisely as in ERC-7579 (under the "Execution Behavior" section). Briefly, `mode` encodes the "behavior" of the execution, which could be a single call, a batch call, a delegatecall, and others. `executionCallData` encodes the data of the execution, which typically includes at least a `target`, a `value`, and a `to` address. - ```solidity pragma solidity 0.8.23; /** + * @notice Action struct is a basic Call struct. * @title Action * @notice This struct represents an action to be taken. - * @dev `mode` and `executionCalldata` are as defined in ERC-7579. + * @dev It only includes the functional part of a transaction, allowing it to be + * agnostic whether this was sent from a protocol-level tx or UserOperation. */ struct Action { - bytes32 mode; - bytes executionCalldata; + address to; + uint256 value; + bytes data; } /** @@ -113,9 +115,9 @@ interface ERC7710Manager { * @notice This method validates the provided data and executes the action if the caller has authority to do so. * @dev the structure of the _authority bytes is determined by the specific Delegation Manager implementation * @param _authority the data used to validate the authority given to execute the action. - * @param _action the action to be executed + * @param _actions an array of actions to be executed atomically */ - function redeemDelegation(bytes calldata _authority, Action calldata _action) external; + function redeemDelegation(bytes calldata _authority, Action[] calldata _actions) external; } ``` @@ -145,23 +147,21 @@ effectively collaborate and adapt to users' needs. ### Execution Interface -A previous iteration of this spec defined `Action` as a simple `(target, value, data)` tuple, and defined a specific +A previous iteration of this spec defined `redeemDelegation` to only take a single `Action`, and defined a specific execution interface on the delegator that is `executeDelegatedAction(Action _action)` which the Delegation Manager is supposed to call. That approach had a few downsides: - Existing smart accounts won't be compatible with this spec (unless they happen to implement the execution interface). -- The execution behavior is limited to a single call, since `Action` could only encode a single call. It made complex - execution behaviors such as batching, delegatecall, and CREATE2 impossible. +- The execution behavior is limited to a single call, since `Action` could only encode a single call. This makes batching + unnecessarily difficult. To solve the first issue, we decided to remove the requirement for the delegator to implement any specific interface. Rather, we rely on the Delegation Manager to correctly call the delegator, and we rely on the fact that a delegator would only create `_authority` for a Delegation Manager that knows how to correctly call it. -To solve the second issue, we decied to adopt the execution interface from ERC-7579, which had to solve a similar problem -within the context of modular smart accounts: defining a standardized execution interface that can support many types of -executions. +To solve the second issue, we decied to update `redeemDelegation` to take an array of `Action`s instead. ## Security Considerations From 7a8cf45e1fbc415051fc4631f7094547b40ad12b Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Sat, 20 Jul 2024 00:33:07 +0800 Subject: [PATCH 4/4] Revert "Remove the 7579 execution interface and use simple batching instead" This reverts commit 6fa941c01062ced07c0eaf07c9a2a8f5599833b7. --- ERCS/erc-7710.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ERCS/erc-7710.md b/ERCS/erc-7710.md index b54b6e60cf..e8084e89d7 100644 --- a/ERCS/erc-7710.md +++ b/ERCS/erc-7710.md @@ -8,7 +8,7 @@ status: Draft type: Standards Track category: ERC created: 2024-05-20 -requires: 1271 +requires: 1271, 7579 --- ## Abstract @@ -70,9 +70,9 @@ Delegator which executes the specified capability on behalf of the Delegator. ```mermaid flowchart LR redeemer(["redeemer"]) --"redeemDelegation"--> Delegation_Manager(["Delegation Manager"]) - Delegation_Manager -.->|validate delegation w/ actions| Delegation_Manager - Delegation_Manager --"execute delegated actions"--> Delegator(["Delegator"]) - Delegator --"executes CALLs using actions"--> Target(["Target"]) + Delegation_Manager -.->|validate delegation w/ Action| Delegation_Manager + Delegation_Manager --"execute delegated action"--> Delegator(["Delegator"]) + Delegator --"executes CALL using Action"--> Target(["Target"]) classDef action stroke:#333,stroke-width:2px,stroke-dasharray: 5, 5; classDef entity fill:#af,stroke:#333,stroke-width:2px; @@ -84,26 +84,24 @@ flowchart LR #### `ERC7710Manager.sol` The Delegation Manager MUST implement the `redeemDelegation` which will be responsible for validating the delegation -being invoked, and will then call the delegator to execute a call for each action in the `_actions` array. If any - call in the array fails, `redeemDelegation` MUST revert. +being invoked, and will then call the delegator to execute the action. The bytes `_authority` passed in as a parameter to the `redeemDelegation` function contains the authority to execute a specific action on behalf of the delegating contract. +The `Action` struct has two fields: `mode` and `executionCalldata`, which are defined precisely as in ERC-7579 (under the "Execution Behavior" section). Briefly, `mode` encodes the "behavior" of the execution, which could be a single call, a batch call, a delegatecall, and others. `executionCallData` encodes the data of the execution, which typically includes at least a `target`, a `value`, and a `to` address. + ```solidity pragma solidity 0.8.23; /** - * @notice Action struct is a basic Call struct. * @title Action * @notice This struct represents an action to be taken. - * @dev It only includes the functional part of a transaction, allowing it to be - * agnostic whether this was sent from a protocol-level tx or UserOperation. + * @dev `mode` and `executionCalldata` are as defined in ERC-7579. */ struct Action { - address to; - uint256 value; - bytes data; + bytes32 mode; + bytes executionCalldata; } /** @@ -115,9 +113,9 @@ interface ERC7710Manager { * @notice This method validates the provided data and executes the action if the caller has authority to do so. * @dev the structure of the _authority bytes is determined by the specific Delegation Manager implementation * @param _authority the data used to validate the authority given to execute the action. - * @param _actions an array of actions to be executed atomically + * @param _action the action to be executed */ - function redeemDelegation(bytes calldata _authority, Action[] calldata _actions) external; + function redeemDelegation(bytes calldata _authority, Action calldata _action) external; } ``` @@ -147,21 +145,23 @@ effectively collaborate and adapt to users' needs. ### Execution Interface -A previous iteration of this spec defined `redeemDelegation` to only take a single `Action`, and defined a specific +A previous iteration of this spec defined `Action` as a simple `(target, value, data)` tuple, and defined a specific execution interface on the delegator that is `executeDelegatedAction(Action _action)` which the Delegation Manager is supposed to call. That approach had a few downsides: - Existing smart accounts won't be compatible with this spec (unless they happen to implement the execution interface). -- The execution behavior is limited to a single call, since `Action` could only encode a single call. This makes batching - unnecessarily difficult. +- The execution behavior is limited to a single call, since `Action` could only encode a single call. It made complex + execution behaviors such as batching, delegatecall, and CREATE2 impossible. To solve the first issue, we decided to remove the requirement for the delegator to implement any specific interface. Rather, we rely on the Delegation Manager to correctly call the delegator, and we rely on the fact that a delegator would only create `_authority` for a Delegation Manager that knows how to correctly call it. -To solve the second issue, we decied to update `redeemDelegation` to take an array of `Action`s instead. +To solve the second issue, we decied to adopt the execution interface from ERC-7579, which had to solve a similar problem +within the context of modular smart accounts: defining a standardized execution interface that can support many types of +executions. ## Security Considerations