Safe and Passkeys
Passkeys are compatible with Safe versions ≥1.3.0.
Safe's standard-agnostic nature allows adding or removing user flows, such as custom signature verification logic. This flexibility facilitates the integration of a Passkeys-based execution flow into a Safe. Safe passkey contracts conform to both ERC-1271 and WebAuthn standards, enabling the verification of signatures for WebAuthn credentials that use the secp256r1 curve.
These contracts can utilize EIP-7212 precompiles for signature verification on supported networks or alternatively employ any verifier contract as a fallback mechanism.
Passkey contracts
SafeWebAuthnSignerProxy
A proxy contract is uniquely deployed for each Passkey signer. The signer information, such as Public key coordinates, Verifier address, and Singleton address, is immutable. All calls to the signer are forwarded to the SafeWebAuthnSignerSingleton contract.
SafeWebAuthnSignerProxy provides gas savings compared to the whole contract deployment for each signer creation.
SafeWebAuthnSignerProxy and SafeWebAuthnSignerSingleton use no storage slots to avoid storage access violations defined in ERC-4337. Check this PR (opens in a new tab) for details on gas savings. This non-standard proxy contract appends signer information, like public key coordinates and verifier data, to the call data before forwarding the calls to the singleton contract.
SafeWebAuthnSignerSingleton
SafeWebAuthnSignerSingleton is a singleton contract that implements the ERC-1271 interface to support signature verification. It enables signature data to be forwarded from a Safe to the WebAuthn library. This contract expects the caller to append public key coordinates and the verifier address (inspired by ERC-2771 (opens in a new tab)).
SafeWebAuthnSignerFactory
The SafeWebAuthnSignerFactory contract deploys the SafeWebAuthnSignerProxy contract with the public key coordinates and verifier information. The factory contract also supports signature verification for the public key and signature information without deploying the signer contract, which is used during the validation of ERC-4337 user operations by the experimental SafeSignerLaunchpad contract.
New signers can be deployed using the ISafeSignerFactory (opens in a new tab) interface and this factory contract address.
WebAuthn
This library generates a signing message, hashing it, and forwards the call to the verifier contract. The WebAuthn library defines a Signature struct containing authenticatorData and clientDataFields, followed by the ECDSA signature's r and s components.
The authenticatorData and clientDataFields are required for generating the signing message. The bytes signature received in the verifySignature(...) function is cast to the Signature struct, so the caller has to take into account formatting the signature bytes as expected by the WebAuthn library.
The code snippet below shows signature encoding for verification using the WebAuthn library.
_10bytes authenticatorData = ...;_10string clientDataFields = ...;_10uint256 r = ...;_10uint256 s = ...;_10// Encode the signature data_10bytes memory signature = abi.encode(authenticatorData, clientDataFields, r, s);
P256
P256 is a library for P256 signature verification with contracts that follow the EIP-7212 EC verify precompile interface. This library defines a custom type Verifiers, which encodes two addresses into a single uint176. The first address (2 bytes) is a precompile address dedicated to verification, and the second (20 bytes) is a fallback address.
This setup allows the library to support networks where the precompile is not yet available. It seamlessly transitions to the precompile when it becomes active while relying on a fallback contract address in the meantime.