Local Account Contracts

ERC-4337 Smart Contracts for Local Account Identity Management


Introduction

The Local Account contracts provide an ERC-4337 compliant account abstraction for managing user identities within the Local network. These contracts leverage P256 elliptic curve cryptography and WebAuthn standards to offer secure, user-friendly authentication mechanisms. The primary goals of these contracts are to:

  • Account Abstraction: Implement ERC-4337 account abstraction to enable advanced functionalities like batching transactions and key rotation.
  • Key Management: Support multiple signing keys (1-of-n multisig) with the ability to add or remove keys.
  • Usability: Provide a seamless user experience without compromising on security by using p256 keys compatible with WebAuthn, compatible with passkeys.
  • Security: Ensure all cryptographic operations are secure.
  • Compatibility: Align with existing and proposed standards like EIP-7212 for future-proofing.

Components

The Local Account system comprises the following on-chain elements:

  • LocalAccount: The main contract representing a user's account.
  • LocalAccountFactory: A factory contract for deploying LocalAccount instances using CREATE2 for deterministic addresses.
  • LocalVerifier: A contract for verifying signatures using P256 elliptic curve operations.
deploys
uses
interacts_with
LocalAccountFactory
LocalAccount
LocalVerifier
IEntryPoint

LocalAccount Contract

Overview

The LocalAccount contract implements an ERC-4337 compatible account abstraction. It allows users to:

  • Execute multiple transactions atomically.
  • Validate user operations via P256 signatures.
  • Manage multiple signing keys with 1-of-n multisig support.
  • Rotate keys securely.

Key Features

  • ERC-4337 Compliance: Implements the IAccount interface for compatibility with account abstraction entry points.
  • Multisig Support: Allows up to 20 active signing keys, enabling 1-of-n multisig functionality.
  • Key Rotation: Supports adding and removing signing keys, enhancing security and flexibility.
  • WebAuthn Integration: Uses P256 keys compatible with WebAuthn, facilitating passwordless authentication.
  • Upgradeable: Utilizes the UUPS upgrade pattern for future enhancements.

State Variables

  • numActiveKeys: Number of active signing keys.
  • keys: Mapping from key slots to public keys.
  • entryPoint: Reference to the ERC-4337 entry point contract.
  • verifier: Instance of the LocalVerifier contract.
  • maxKeys: Maximum number of signing keys (constant value of 20).

Methods

Initialization

function initialize(
    uint8 slot,
    bytes32[2] calldata key,
    Call[] calldata initCalls
) public virtual initializer
  • Purpose: Initializes the account with an initial signing key and optional contract calls.
  • Parameters:
    • slot: Key slot to store the initial key.
    • key: The P256 public key.
    • initCalls: Array of contract calls to execute during initialization.

Transaction Execution

function executeBatch(Call[] calldata calls) external onlyEntryPoint
  • Purpose: Executes multiple transactions atomically.
  • Parameters:
    • calls: An array of Call structs containing destination, value, and data.

User Operation Validation

function validateUserOp(
    UserOperation calldata userOp,
    bytes32 userOpHash,
    uint256 missingAccountFunds
) external override returns (uint256 validationData)
  • Purpose: Validates a user operation by verifying a P256 signature.
  • Parameters:
    • userOp: The user operation to validate.
    • userOpHash: Hash of the user operation.
    • missingAccountFunds: Amount of funds the account needs to cover transaction costs.

Signature Validation

function isValidSignature(
    bytes32 message,
    bytes calldata signature
) external view override returns (bytes4 magicValue)
  • Purpose: Validates signatures for ERC-1271 compliance.
  • Parameters:
    • message: The message hash that was signed.
    • signature: The signature data.

Key Management

  • Add Signing Key

    function addSigningKey(uint8 slot, bytes32[2] memory key) public onlySelf
    • Purpose: Adds a new signing key to the account.
    • Parameters:
      • slot: The key slot to store the new key.
      • key: The P256 public key.
  • Remove Signing Key

    function removeSigningKey(uint8 slot) public onlySelf
    • Purpose: Removes an existing signing key from the account.
    • Parameters:
      • slot: The key slot of the key to remove.

Utility Methods

  • Get Active Signing Keys

    function getActiveSigningKeys()
        public
        view
        returns (
            bytes32[2][] memory activeSigningKeys,
            uint8[] memory activeSigningKeySlots
        )
    • Purpose: Retrieves all active signing keys and their slots.

Access Control

  • onlySelf: Modifier to restrict functions to be called only by the contract itself.
  • onlyEntryPoint: Modifier to restrict functions to be called only by the designated entry point.

Events

  • AccountInitialized: Emitted during initialization.
  • SigningKeyAdded: Emitted when a new signing key is added.
  • SigningKeyRemoved: Emitted when a signing key is removed.

LocalAccountFactory Contract

Overview

The LocalAccountFactory contract is responsible for deploying new LocalAccount instances using the CREATE2 opcode, allowing for deterministic contract addresses.

Key Features

  • Deterministic Deployment: Uses CREATE2 for predictable account addresses.
  • Prefunding: Allows prefunding of the account during creation.
  • Singleton Implementation: Reuses a single LocalAccount implementation for all instances.

Methods

Create Account

function createAccount(
    uint8 keySlot,
    bytes32[2] memory key,
    LocalAccount.Call[] calldata initCalls,
    uint256 salt
) public payable returns (LocalAccount ret)
  • Purpose: Deploys a new LocalAccount contract or returns the address if it already exists.
  • Parameters:
    • keySlot: Key slot for the initial key.
    • key: The P256 public key.
    • initCalls: Array of initialization calls.
    • salt: Salt value for CREATE2.

Get Address

function getAddress(
    uint8 keySlot,
    bytes32[2] memory key,
    LocalAccount.Call[] calldata initCalls,
    uint256 salt
) public view returns (address)
  • Purpose: Computes the deterministic address of a LocalAccount contract based on input parameters.

LocalVerifier Contract

Overview

The LocalVerifier contract provides signature verification functionality for P256 signatures, compatible with WebAuthn standards.

Key Features

  • Signature Verification: Verifies P256 signatures for both user operations and ERC-1271 compliance.
  • Upgradeable: Implements the UUPS upgrade pattern for future enhancements.
  • Auditability: Designed with security and auditability in mind.

Methods

Verify Signature

function verifySignature(
    bytes memory message,
    bytes calldata signature,
    uint256 x,
    uint256 y
) public view returns (bool)
  • Purpose: Verifies a P256 signature given the message, signature data, and public key coordinates.
  • Parameters:
    • message: The original message that was signed.
    • signature: The signature data, including WebAuthn-related fields.
    • x, y: Coordinates of the public key on the P256 curve.

Signature Structure

The signature used in the LocalAccount contract follows a specific structure:

  • Signature Format:

    struct Signature {
        bytes authenticatorData;
        string clientDataJSON;
        uint256 challengeLocation;
        uint256 responseTypeLocation;
        uint256 r;
        uint256 s;
    }
  • Components:

    • authenticatorData: Data from the authenticator device.
    • clientDataJSON: JSON-encoded client data.
    • challengeLocation: Offset of the challenge in clientDataJSON.
    • responseTypeLocation: Offset of the response type in clientDataJSON.
    • r, s: Signature components.

Access Control

  • onlyOwner: Modifier restricting functions to the contract owner.
  • Ownership Transfer: Ownership can be transferred to enable upgrades or burned to make the contract immutable.

Key Concepts

ERC-4337 Account Abstraction

ERC-4337 introduces account abstraction, allowing smart contract accounts to manage their own authentication and transaction validation logic. The LocalAccount leverages this standard to provide flexible and secure account management.

P256 Elliptic Curve Cryptography

The contracts utilize the P256 elliptic curve for cryptographic operations, ensuring strong security guarantees. P256 is widely used in WebAuthn implementations, facilitating compatibility with modern authentication standards.

WebAuthn Integration

By integrating with WebAuthn, users can authenticate using hardware security modules, biometric sensors, or other secure methods without relying on traditional private keys or seed phrases.

Additional Context

Gas Optimization

While smart contract-based signature verification is more gas-intensive than native precompiles, the LocalVerifier is optimized for efficiency:

  • Strauss-Shamir Trick: Optimizes scalar multiplication in elliptic curve operations.
  • Extended Jacobian Coordinates: Enhances efficiency in point addition and doubling.
  • Progressive Precompiles: The design anticipates future EVM improvements, such as the proposed EIP-7212 precompile, which would significantly reduce gas costs.

Future Enhancements

  • EIP-7212 Compatibility: The contracts are designed to be compatible with the proposed EIP-7212, allowing for potential gas cost reductions if the precompile is adopted.
  • Key Rotation Replay Protection: Future versions may include cross-chain replay protection for key rotations.

References