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.
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 theLocalVerifier
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 ofCall
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 inclientDataJSON
.responseTypeLocation
: Offset of the response type inclientDataJSON
.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
- EIP-4337: Account Abstraction
- EIP-7212: P256 Precompile Proposal
- WebAuthn Specification
- P256 Elliptic Curve Details
- Wycheproof Test Vectors
- Strauss-Shamir Trick
- Extended Jacobian Coordinates