-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor WebAuthn Implementation (#320)
This PR refactors the WebAuthn implementation into a library instead of split into multiple contracts. This removes the amount of `CALL`s required for verifying a signature. I did some analysis on the deployment vs. signature verification costs comparing this code, `main` and this change incorporating optimizations from #289 and found this: | setup | deployment | verification (dummy) | break even | | ------------------------------------ | ---------- | -------------------- | ---------- | | main (viaIR = false) | 373543 | 17789 | 0 | | main (viaIR = true) | 393494 | 16443 | 15 | | this branch (viaIR = false) | 612123 | 13835 | 61 | | this branch (viaIR = true) | 594058 | 12551 | 43 | | base64 optimizations (viaIR = false) | 442545 | 12965 | 15 | | base64 optimizations (viaIR = true) | 414941 | 11102 | 7 | Meaning that after 7 signatures, even with the slightly larger deployment costs, we would break even by avoiding the extra `CALL` (noting that ABI-encoding the call to the `WebAuthnVerifier` is not particularly efficient in the first place).
- Loading branch information
Showing
17 changed files
with
289 additions
and
429 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,15 +6,17 @@ import {PackedUserOperation} from "@account-abstraction/contracts/interfaces/Pac | |
import {_packValidationData} from "@account-abstraction/contracts/core/Helpers.sol"; | ||
import {SafeStorage} from "@safe-global/safe-contracts/contracts/libraries/SafeStorage.sol"; | ||
|
||
import {ICustom256BitECSignerFactory} from "../interfaces/ICustomSignerFactory.sol"; | ||
import {ICustomECDSASignerFactory} from "../interfaces/ICustomECDSASignerFactory.sol"; | ||
import {ISafe} from "../interfaces/ISafe.sol"; | ||
import {ERC1271} from "../libraries/ERC1271.sol"; | ||
|
||
/** | ||
* @title SafeOpLaunchpad - A contract for Safe initialization with custom unique signers that would violate ERC-4337 factory rules. | ||
* @dev The is intended to be set as a Safe proxy's implementation for ERC-4337 user operation that deploys the account. | ||
* @title Safe Launchpad for Custom ECDSA Signing Schemes. | ||
* @dev A launchpad account implementation that enables the creation of Safes that use custom ECDSA | ||
* signing schemes that require additional contract deployments over ERC-4337. | ||
* @custom:security-contact [email protected] | ||
*/ | ||
contract Safe256BitECSignerLaunchpad is IAccount, SafeStorage { | ||
contract SafeECDSASignerLaunchpad is IAccount, SafeStorage { | ||
bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = keccak256("EIP712Domain(uint256 chainId,address verifyingContract)"); | ||
|
||
// keccak256("SafeSignerLaunchpad.initHash") - 1 | ||
|
@@ -189,13 +191,7 @@ contract Safe256BitECSignerLaunchpad is IAccount, SafeStorage { | |
bytes memory operationData = _getOperationData(userOpHash, validAfter, validUntil); | ||
bytes32 operationHash = keccak256(operationData); | ||
try | ||
ICustom256BitECSignerFactory(signerFactory).isValidSignatureForSigner( | ||
signerX, | ||
signerY, | ||
signerVerifier, | ||
operationHash, | ||
signature | ||
) | ||
ICustomECDSASignerFactory(signerFactory).isValidSignatureForSigner(operationHash, signature, signerX, signerY, signerVerifier) | ||
returns (bytes4 magicValue) { | ||
// The timestamps are validated by the entry point, therefore we will not check them again | ||
validationData = _packValidationData(magicValue != ERC1271.MAGIC_VALUE, validUntil, validAfter); | ||
|
@@ -218,7 +214,7 @@ contract Safe256BitECSignerLaunchpad is IAccount, SafeStorage { | |
SafeStorage.singleton = singleton; | ||
{ | ||
address[] memory owners = new address[](1); | ||
owners[0] = ICustom256BitECSignerFactory(signerFactory).createSigner(signerX, signerY, signerVerifier); | ||
owners[0] = ICustomECDSASignerFactory(signerFactory).createSigner(signerX, signerY, signerVerifier); | ||
|
||
ISafe(address(this)).setup(owners, 1, setupTo, setupData, fallbackHandler, address(0), 0, payable(address(0))); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53 changes: 53 additions & 0 deletions
53
modules/passkey/contracts/interfaces/ICustomECDSASignerFactory.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
pragma solidity >=0.8.0 <0.9.0; | ||
|
||
/** | ||
* @title Custom ECDSA Signer Factory | ||
* @dev Interface for a factory contract that can create ERC-1271 compatible signers, and verify | ||
* signatures for custom ECDSA schemes. | ||
* @custom:security-contact [email protected] | ||
*/ | ||
interface ICustomECDSASignerFactory { | ||
/** | ||
* @notice Gets the unique signer address for the specified data. | ||
* @dev The unique signer address must be unique for some given data. The signer is not | ||
* guaranteed to be created yet. | ||
* @param x The x-coordinate of the public key. | ||
* @param y The y-coordinate of the public key. | ||
* @param verifier The address of the verifier. | ||
* @return signer The signer address. | ||
*/ | ||
function getSigner(uint256 x, uint256 y, address verifier) external view returns (address signer); | ||
|
||
/** | ||
* @notice Create a new unique signer for the specified data. | ||
* @dev The unique signer address must be unique for some given data. This must not revert if | ||
* the unique owner already exists. | ||
* @param x The x-coordinate of the public key. | ||
* @param y The y-coordinate of the public key. | ||
* @param verifier The address of the verifier. | ||
* @return signer The signer address. | ||
*/ | ||
function createSigner(uint256 x, uint256 y, address verifier) external returns (address signer); | ||
|
||
/** | ||
* @notice Verifies a signature for the specified address without deploying it. | ||
* @dev This must be equivalent to first deploying the signer with the factory, and then | ||
* verifying the signature with it directly: | ||
* `factory.createSigner(signerData).isValidSignature(message, signature)` | ||
* @param message The signed message. | ||
* @param signature The signature bytes. | ||
* @param x The x-coordinate of the public key. | ||
* @param y The y-coordinate of the public key. | ||
* @param verifier The address of the verifier. | ||
* @return magicValue Returns the ERC-1271 magic value when the signature is valid. Reverting or | ||
* returning any other value implies an invalid signature. | ||
*/ | ||
function isValidSignatureForSigner( | ||
bytes32 message, | ||
bytes calldata signature, | ||
uint256 x, | ||
uint256 y, | ||
address verifier | ||
) external view returns (bytes4 magicValue); | ||
} |
87 changes: 0 additions & 87 deletions
87
modules/passkey/contracts/interfaces/ICustomSignerFactory.sol
This file was deleted.
Oops, something went wrong.
56 changes: 0 additions & 56 deletions
56
modules/passkey/contracts/interfaces/IWebAuthnVerifier.sol
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.