From 82b624e60938d5131724e44d8a013ea2f85bc3af Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 19 Mar 2025 10:13:42 -0700 Subject: [PATCH 1/4] Improved ERC in response to feedback on ethereum magicians --- ERCS/erc-7710.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/ERCS/erc-7710.md b/ERCS/erc-7710.md index baece8a3242..6ac800447d4 100644 --- a/ERCS/erc-7710.md +++ b/ERCS/erc-7710.md @@ -37,6 +37,18 @@ development time but also results in higher deployment and execution gas costs. interactions limits the ability to adapt to new requirements or to delegate specific, limited permissions in a dynamic manner. +Additionally, the need to repeatedly sign messages for each interaction creates friction in user experiences, particularly in scenarios requiring frequent or automated interactions. + +The proposed standard aims to solve these challenges by enabling the creation of long-lived sessions and delegated permissions through a single signature. These delegations can be used to: +- Establish persistent sessions with dApps that don't require repeated signing +- Grant bounded permissions to AI agents or automated systems +- Create shareable invite links with specific capabilities +- Enable third-party delegates to act within well-defined policy constraints + +By allowing the creation of open-ended yet policy-constrained delegations with a single signature, this standard helps +minimize user interactions while maximizing their meaningful content. Users can grant specific capabilities with +clear boundaries, rather than repeatedly signing similar permissions. + The proposed standard aims to simplify and standardize the process of delegation between contracts, reducing the operational complexity and gas costs associated with shared capabilities. By establishing a common framework for delegating permissions, we can streamline interactions within the Ethereum ecosystem, making contracts more flexible, @@ -51,12 +63,15 @@ RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as de ### Terms - A **Delegator** is a smart contract that can create a delegation. -- A **Delegation Manager** is a singleton smart contract that is responsible for validating delegation authority and - calling on the *Delegator* to execute an action. It implements the `ERC7710Manager` interface. +- A **Delegation Manager** is a smart contract that validates delegation authority and calls on the *Delegator* to execute an action. It implements the `ERC7710Manager` interface. A Delegation Manager verifies and processes delegation redemptions, and multiple Delegation Managers can exist with different implementations. A contract account can be its own delegation manager. - A **delegation** is an authority given to another address to perform a specific action. - A **delegate** is a smart contract, smart contract account, or EOA that has authority to redeem a delegation. - A **redeemer** is a *delegate* that is using a delegation. +### Obtaining Delegations + +The process by which a delegate obtains a delegation is intentionally left out of scope for this ERC. This ERC focuses solely on the interface for redeeming delegations and the validation of delegation authority. The mechanism for requesting and granting delegations may be implemented in various ways depending on the use case, such as through [ERC-7715](./eip-7715.md) or other protocols. This separation of concerns allows for flexibility in how delegations are created while maintaining a consistent interface for their redemption. + ### Overview #### Redeeming a Delegation @@ -80,6 +95,18 @@ specific action on behalf of the delegating contract. The bytes32 array `_modes` and the bytes array `_executionCallDatas` passed in as parameters to the `redeemDelegations` function are arrays of `mode` and `executionCalldata`, which are defined precisely in [ERC-7579](./eip-7579.md) (under the "Execution Behavior" section). Briefly, `mode` encodes the "behavior" of the execution, which could be a single call, a batch call, and others. `executionCallData` encodes the data of the execution, which typically includes at least a `target`, a `value`, and a `to` address. +The three arrays MUST be interpreted as a list of tuples, where each tuple consists of (`_permissionContexts[i]`, `_modes[i]`, `_executionCallDatas[i]`). The function MUST revert if the arrays have different lengths. Each tuple represents a single delegation redemption with its associated permission context, execution mode, and execution data. Implementations MUST enforce atomicity of the batch. + +#### Permission Verification + +While this interface does not include an explicit method for checking delegation permissions, dApps SHOULD verify permissions before attempting to execute actions by: + +1. Simulating the `redeemDelegations` call with the intended parameters +2. Using the simulation results to determine if the delegation would succeed +3. If the simulation fails, the dApp can request new or updated permissions from the user + +This simulation-based approach provides stronger guarantees than a method exposed by the delegation manager, as it validates the entire execution context rather than the claims of the delegation manager. + ```solidity pragma solidity 0.8.23; @@ -140,6 +167,18 @@ To solve the second issue, we decied to adopt the execution interface from [ERC- within the context of modular smart accounts: defining a standardized execution interface that can support many types of executions. +## Reference Implementation + +For a complete reference implementation of a Delegation Manager, see the [MetaMask Delegation Framework](https://github.com/MetaMask/delegation-framework/blob/acaa68bbe99eb73d08a4b9f70e78530ed0943dc3/src/DelegationManager.sol#L126). This implementation includes features such as: + +- EIP-712 signature validation for delegations +- Support for both EOA and contract signatures (ERC-1271) +- Caveat enforcement for fine-grained delegation control +- Batch delegation processing +- Delegation revocation mechanisms + +The MetaMask implementation demonstrates one way to build a robust delegation system while adhering to this standard's interface requirements. + ## Security Considerations The introduction of customizable authorization terms requires careful consideration of how authorization data is @@ -147,6 +186,15 @@ structured and interpreted. Potential security risks include the misinterpretati unauthorized actions being taken if the interface is not properly implemented. It is recommended that applications implementing this interface undergo thorough security audits to ensure that authorization terms are handled securely. +### Permission Verification + +dApps MUST NOT assume that having received a delegation in the past guarantees future execution rights. Delegations can be revoked, expire, or become invalid due to state changes. To ensure reliable operation: + +1. Always simulate delegation redemptions before submitting them on-chain +2. Handle simulation failures gracefully by requesting new permissions when needed +3. Consider implementing retry logic with escalating permission requests +4. Be prepared for delegations to become invalid between simulation and execution + Needs discussion. ## Copyright From 1a9c11192d5aaefc802e15cac533fd2b480e0b39 Mon Sep 17 00:00:00 2001 From: Ryan <81343914+McOso@users.noreply.github.com> Date: Thu, 20 Mar 2025 11:45:58 -0400 Subject: [PATCH 2/4] fix(7710): absolute urls --- ERCS/erc-7710.md | 4 +- assets/erc-7710/Example7710Manager.sol | 133 +++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 assets/erc-7710/Example7710Manager.sol diff --git a/ERCS/erc-7710.md b/ERCS/erc-7710.md index 6ac800447d4..809e04e1300 100644 --- a/ERCS/erc-7710.md +++ b/ERCS/erc-7710.md @@ -169,7 +169,9 @@ executions. ## Reference Implementation -For a complete reference implementation of a Delegation Manager, see the [MetaMask Delegation Framework](https://github.com/MetaMask/delegation-framework/blob/acaa68bbe99eb73d08a4b9f70e78530ed0943dc3/src/DelegationManager.sol#L126). This implementation includes features such as: +For a minimal reference implementation focusing on delegation redemption, please see [Example7710Manager](../assets/erc-7710/Example7710Manager.sol). + +For a complete reference implementation of a Delegation Manager, see the MetaMask Delegation Framework, which includes features such as: - EIP-712 signature validation for delegations - Support for both EOA and contract signatures (ERC-1271) diff --git a/assets/erc-7710/Example7710Manager.sol b/assets/erc-7710/Example7710Manager.sol new file mode 100644 index 00000000000..f6eec46e8a1 --- /dev/null +++ b/assets/erc-7710/Example7710Manager.sol @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { IERC7579Account } from "../erc-7579/IMSA.sol"; + +/** + * @title Example7710Manager + * @notice Not for production use.A minimal reference implementation for ERC-7710 focusing on delegation redemption. + * @dev This is an intentionally simplified implementation to demonstrate core concepts. + * For a complete production implementation with features like conditional permission enforcement and revocation, see MetaMask's Delegation Framework: + * https://github.com/MetaMask/delegation-framework/blob/main/src/DelegationManager.sol + */ +contract Example7710Manager { + ////////////////////////////// Types ////////////////////////////// + + struct Delegation { + address delegator; // The address delegating authority + address delegate; // The address receiving authority + bytes32 authority; // The authority being delegated (or ROOT_AUTHORITY) + bytes signature; // The delegator's signature authorizing this delegation + } + + ////////////////////////////// Errors ////////////////////////////// + + error TupleDataLengthMismatch(); + error InvalidDelegate(); + error InvalidAuthority(); + error InvalidSignature(); + + ////////////////////////////// Constants ////////////////////////////// + + /// @dev Special authority value indicating the delegator is the root authority + bytes32 public constant ROOT_AUTHORITY = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; + + ////////////////////////////// External Methods ////////////////////////////// + + /** + * @notice Validates and executes delegated actions through a chain of authority. + * @param _permissionContexts Array of delegation chains, each ordered from leaf to root. + * Each chain demonstrates authority where: + * - Index 0 is the leaf delegation (msg.sender's authority) + * - Each delegation points to its authority via the previous delegation's hash + * - The last delegation must have ROOT_AUTHORITY + * @param _modes Execution modes for each action (see ERC-7579) + * @param _executionCallDatas Encoded actions to execute + */ + function redeemDelegations( + bytes[] calldata _permissionContexts, + bytes32[] calldata _modes, + bytes[] calldata _executionCallDatas + ) external { + uint256 batchSize_ = _permissionContexts.length; + if (batchSize_ != _executionCallDatas.length || batchSize_ != _modes.length) { + revert TupleDataLengthMismatch(); + } + + Delegation[][] memory batchDelegations_ = new Delegation[][](batchSize_); + + // Process each batch + for (uint256 batchIndex_; batchIndex_ < batchSize_; ++batchIndex_) { + Delegation[] memory delegations_ = abi.decode(_permissionContexts[batchIndex_], (Delegation[])); + + batchDelegations_[batchIndex_] = delegations_; + + // Validate caller is the delegate + if (delegations_[0].delegate != msg.sender) { + revert InvalidDelegate(); + } + + // Validate each delegation in chain + for (uint256 i = 0; i < delegations_.length; i++) { + Delegation memory delegation_ = delegations_[i]; + bytes32 delegationHash_ = _getDelegationHash(delegation_); + + // Note: In a production implementation, you would want to use EIP-712 for typed data signing + // and proper signature validation for both EOA and contract signatures. + // This is simplified for demonstration purposes. + if (!_isValidSignature(delegationHash_, delegation_.signature, delegation_.delegator)) { + revert InvalidSignature(); + } + + // Validate authority chain + if (i != delegations_.length - 1) { + if (delegation_.authority != _getDelegationHash(delegations_[i + 1])) { + revert InvalidAuthority(); + } + // Validate delegate chain + address nextDelegate_ = delegations_[i + 1].delegate; + if (delegation_.delegator != nextDelegate_) { + revert InvalidDelegate(); + } + } else if (delegation_.authority != ROOT_AUTHORITY) { + revert InvalidAuthority(); + } + } + + // Execute the delegated action on the root delegator + IERC7579Account(delegations_[delegations_.length - 1].delegator).executeFromExecutor( + _modes[batchIndex_], + _executionCallDatas[batchIndex_] + ); + } + } + + ////////////////////////////// Internal Methods ////////////////////////////// + + /** + * @notice Creates a simple hash of a Delegation struct + * @dev In production, use EIP-712 for typed data hashing + */ + function _getDelegationHash(Delegation memory delegation) internal pure returns (bytes32) { + return keccak256(abi.encode( + delegation.delegator, + delegation.delegate, + delegation.authority + )); + } + + /** + * @notice Basic signature validation (simplified for example purposes) + * @dev In production, use EIP-712 and proper signature validation + */ + function _isValidSignature( + bytes32 hash, + bytes memory signature, + address signer + ) internal pure returns (bool) { + // ECDSA recover + // or ERC1271 isValidSignature + // Logic would go here + return true; // Simplified for example + } +} \ No newline at end of file From 0fa4e3fc9a099540084cd6cd0a3034e35e5235fc Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 2 Apr 2025 12:39:57 -0700 Subject: [PATCH 3/4] Split up line --- ERCS/erc-7710.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ERCS/erc-7710.md b/ERCS/erc-7710.md index 809e04e1300..8cc4e57a606 100644 --- a/ERCS/erc-7710.md +++ b/ERCS/erc-7710.md @@ -123,7 +123,11 @@ interface ERC7710Manager { * @param _modes the array of modes to execute the related executioncallData * @param _executionCallDatas the array of encoded executions to be executed */ - function redeemDelegations(bytes[] calldata _permissionContexts, bytes32[] calldata _modes, bytes[] calldata _executionCallDatas) external; + function redeemDelegations( + bytes[] calldata _permissionContexts, + bytes32[] calldata _modes, + bytes[] calldata _executionCallData + ) external; } ``` From 2e1e5710199bc9f90869db30cb799dbd3d15c9cb Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Wed, 2 Apr 2025 12:58:16 -0700 Subject: [PATCH 4/4] Update ERCS/erc-7710.md Co-authored-by: Ryan <81343914+McOso@users.noreply.github.com> --- ERCS/erc-7710.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ERCS/erc-7710.md b/ERCS/erc-7710.md index 8cc4e57a606..b66e540b4ae 100644 --- a/ERCS/erc-7710.md +++ b/ERCS/erc-7710.md @@ -177,7 +177,7 @@ For a minimal reference implementation focusing on delegation redemption, please For a complete reference implementation of a Delegation Manager, see the MetaMask Delegation Framework, which includes features such as: -- EIP-712 signature validation for delegations +- [EIP-712](./eip-712.md) signature validation for delegations - Support for both EOA and contract signatures (ERC-1271) - Caveat enforcement for fine-grained delegation control - Batch delegation processing