Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7780: Validation Module Extension for ERC-7579

Introduces new smart account module types for signature validation and permissioning

Authors zeroknots (@zeroknots), Konrad Kopp (@kopy-kat), Taek Lee (@leekt), Fil Makarov (@filmakarov)
Created 2024-10-01
Discussion Link https://ethereum-magicians.org/t/erc-7780-validation-module-extension-for-erc-7579/21273
Requires EIP-7579

Abstract

This proposal introduces three new module types on top of the existing modules described in ERC-7579. The modules are policy, signer and stateless validator. None of these modules are required to be implemented by accounts, but accounts can choose to implement them or other modules can choose to make use of them for additional composability.

Policy modules can be used to check what a UserOperation or action is trying to achieve and determine if this is allowed. Signer modules can be used to validate signatures on provided hashes. Stateless validators are modules that are used to both validate signatures and compare them to a calldata-provided data blob which could, for example, include owners to check signatures against.

Motivation

The modules introduced by this proposal aim to create more composability around signature and permission verification.

Policy and signer modules allow an account to make direct use of such a permissioning logic rather than relying on external modules to handle this. This has the upside of lower gas cost but the downside of less flexibility for users and developers that use the account.

Stateless validators enable further composability around signature validation logic. In many cases, it does not make sense to re-write signature validation for new validators, but instead to use the existing ones. However, this is usually not possible since the validators rely on a stored configuration indexed by the msg.sender, which is expected to be an account. Stateless validators solve this problem by not relying on state to compare signature verficiation against, but instead to compare it against a calldata-provided argument.

Specification

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.

This standard introduces three new module types on top of the existing modules introduced by ERC-7579:

  • Policy (type id: 5)
  • Signer (type id: 6)
  • Stateless Validator (type id: 7)

Note: A single module can be of multiple types.

Policy

Policies MUST implement ERC-7579’s IModule and the IPolicy interface and have module type id: 5.

interface IPolicy is IModule {

		/**
		 * Checks a userOp to determine if it should be executed
         *
         * SHOULD validate the executions in the userOp against stored configurations
         *
		 * @param id The id of the policy
		 * @param userOp The user operation to check
         *
		 * @return The validation data to return to the EntryPoint as specified by ERC-4337
		 */
	  function checkUserOpPolicy(
			  bytes32 id,
			  PackedUserOperation calldata userOp
		)
        external
        payable
        virtual
        returns (uint256);

		/**
		 * Checks a signature to determine if it should be executed
         *
         * SHOULD validate the hash in order to determine what the signature is used for and if it should be permitted
         * MAY check the sender to determine whether the signature should be permitted
         *
		 * @param id The id of the policy
		 * @param sender The sender of the transaction
		 * @param hash The hash of the transaction
		 * @param sig The signature of the transaction
         *
		 * @return The validation data to return to the EntryPoint as specified by ERC-4337
		 */
		function checkSignaturePolicy(
		    bytes32 id,
			  address sender,
			  bytes32 hash,
			  bytes calldata sig
		)
        external
        view
        virtual
        returns (uint256);
}

Signer

Signers MUST implement the IModule and the ISigner interface and have module type id: 6.

interface ISigner is IModule {

		/**
		 * Check the signature of a user operation
         *
		 * @param id The id of the signer config
		 * @param userOp The user operation
		 * @param userOpHash The hash of the user operation
         *
		 * @return The status of the signature check to return to the EntryPoint
		 */
    function checkUserOpSignature(
		    bytes32 id,
			  PackedUserOperation calldata userOp,
			  bytes32 userOpHash
		)
        external
        payable
        virtual
        returns (uint256);

		/**
		 * Check an ERC-1271 signature
         *
		 * @param id The id of the signer config
		 * @param sender The sender of the signature
		 * @param hash The hash to check against
		 * @param sig The signature to validate
         *
		 * @return The ERC-1271 magic value if the signature is valid
		 */
    function checkSignature(
		    bytes32 id,
		    address sender,
		    bytes32 hash,
		    bytes calldata sig
		)
        external
        view
        virtual
        returns (bytes4);
}

Stateless Validator

Validators MUST implement the IStatelessValidator interface and have module type id: 7. It is RECOMMENDED that all Validators (module type id 1) also implement the Stateless Validator interface for additional composabillity.

interface IStatelessValidator {

	/**
     * Validates a signature given some data
     *
     * @param hash The data that was signed over
     * @param signature The signature to verify
     * @param data The data to validate the verified signature agains
     *
     * MUST validate that the signature is a valid signature of the hash
     * MUST compare the validated signature against the data provided
     * MUST return true if the signature is valid and false otherwise
     */
    function validateSignatureWithData(
        bytes32 hash,
        bytes calldata signature,
        bytes calldata data
    )
        external
        view
        returns (bool);

     /**
     * Returns boolean value if module is a certain type
     *
     * @param moduleTypeId the module type ID according the ERC-7579 spec
     *
     * MUST return true if the module is of the given type and false otherwise
     */
    function isModuleType(uint256 moduleTypeId) external view returns (bool);
}

Rationale

TBD

Backwards Compatibility

No backward compatibility issues found.

Security Considerations

TBD

Copyright and related rights waived via CC0.

Citation

Please cite this document as:

zeroknots (@zeroknots), Konrad Kopp (@kopy-kat), Taek Lee (@leekt), Fil Makarov (@filmakarov), "ERC-7780: Validation Module Extension for ERC-7579 [DRAFT]," Ethereum Improvement Proposals, no. 7780, October 2024. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7780.