-
Notifications
You must be signed in to change notification settings - Fork 82
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[4337] Launchpad Account Deployer to Work Around 4337 Limitations #149
Comments
nlordell
changed the title
Launchpad Account Deployer to Work Around 4337 Limitations
[4337] Launchpad Account Deployer to Work Around 4337 Limitations
Nov 13, 2023
This was referenced Nov 13, 2023
Closed
This was referenced Nov 20, 2023
nlordell
added a commit
that referenced
this issue
Nov 24, 2023
Fixes #148 This PR introduces an E2E test using the official bundler where we deploy a Safe that uses a custom (and silly 🤪) signing scheme over ERC-1271. Specifically, the signing scheme is deployed as a singleton contract that can be shared by multiple Safes using a `mapping(safe => data)` to differentiate between signers. In theory, this could be adapted to, for example, checking a signature using P256 curve in order to integrate with WebAuthn, and is meant to “prove” that the Safe with the ERC-4337 module would work with existing WebAuthn signer implementations. The actual implementation is a little convoluted for a few reasons. Namely, ERC-4337 only allows a **single** `CREATE2` per user operation that **MUST** result in the `userOp.sender` account. Because of this, deploying ad-hoc signers in the `Safe.setup` call is not possible, and we have instead opted for a “singleton signer” pattern, where the logic for verifying signatures is shared and a mapping is used to store per-Safe context relevant to signature verification. Additionally, In order for this to work with ERC-4337, a staked factory is needed (as accessing associated storage for user operations with `initCode` require a factory). Unfortunately, staked factories add all kinds of complexities: - Currently, the staked factory contract is quite dumb (can only stake, but can’t unstake). A full staked factory contract requires us to iron out some requirements and make a proper implementation with documentation and tests (out of scope for this PR and issue, and a non-trivial amount of work) - Staking is determined per bundler, so while some amount of stake may be sufficient for a bundler, it may not be sufficient for all (which adds additional off-chain management dependencies). **For these reasons, I would recommend exploring #149**.
This was referenced Nov 30, 2023
Two different approaches, each with their pros/cons, were proposed in: |
Out of curiosity, have you looked into how other projects solve this? Also, another (dirty but wcyd) approach to consider is getting bundlers to whitelist our factory or similar. I know some bundlers do that for some ERC20 tokens to enable ERC20 payments. |
nlordell
added a commit
that referenced
this issue
Dec 13, 2023
Related to #149, follow-up to #182 This PR provides another approach to Safe initialization to accommodate for custom signers that are deployed along with the Safe. See #182 for more context. This launchpad implementation is very specific to custom signers and introduces a new `IUniqueSignerFactory` interface that must be implemented to work with it. The name “unique” signer is not great, but named this way since for a given factory and some “signer data”, a `ISignatureVerifier` implementation will correspond to a **unique** address. In the example of P-256 and WebAuthn signers, this means a P-256 public key will correspond to a unique on-chain address with an `ISignatureVerifier` implementation. This implementation works by tying the Safe address to the `signerFactory`, `signerData` and Safe `setup` parameters. This means a couple of things: 1. The Safe address is unique for a specific initial configuration (owner, singleton, fallback, modules, etc.); the same property holds for the existing `SafeProxyFactory` 2. Unlike #182, the Safe address **is not** tied to the first user operation (in fact, the user operation is signed with the same owner as the Safe will use!) ```mermaid sequenceDiagram actor B as Bundler participant E as EntryPoint participant F as SafeProxyFactory participant P as SafeProxy (Account) participant L as SafeSignerLaunchpad participant S as Safe (Singleton) participant M as Safe4337Module participant U as IUniqueSignerFactory participant A as Signer actor T as Target B ->> +E: handleOps([userOp]) E ->> +F: CALL(userOp.initCode[:20]) F ->> P: CREATE2 F ->> P: setup(initHash) P ->> L: setup(initHash) note over L: SSTORE(initHash) F -->> -E: ok E ->> +P: validateUserOp(userOp) P ->> +L: validateUserOp(userOp) note over L: require(getInitHash(userOp) == initHash) L ->> +U: isValidSignatureForSigner(operationData, signature, signerData) U -->> -L: magic L -->> -P: validationData P -->> -E: validationData E ->> +P: initializeThenUserOp<br>(singleton, signerFactory, signerData, ...setupParams, callData) P ->> L: initializeThenUserOp(…) note over L: SafeStorage.singleton = singleton L ->> +U: createSigner(signerData) U ->> A: CREATE2 U -->> -L: owner L ->> S: setup([owner], 1, ...setupParams) note over S: standard Safe setup L ->> P: DELEGATECALL(callData) P ->> S: DELEGATECALL(callData) S ->> M: execUserOp(…) M ->> P: executeFromModule(…) P ->> S: executeFromModule(…) S ->> T: Ether P -->> -E: ok ``` ### Implementation Notes Currently, the implementation only supports a single signer, but can be changed to support multiple (by turning `signerFactory` and `signerData` into arrays). ### Downsides The downsides of this implementation over #182 is that it is a solution _very_ specific to deploying Safes with custom signing schemes that require additional contract deployments and not a general solution to complex Safe setups in the context of ERC-4337.
Not yet. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Context / issue
The 4337 module currently allows creating a new account (using
UserOperation.initCode
) and executing an action atomically.Furthermore, support for additional signing schemes (such as WebAuthn using P256 curve signatures) is already supported by the Safe by creating a dedicated signer contract per owner (in the case of WebAuthn, one contract per public key) implementing the signature validation logic using ERC-1271.
However, ERC-4337 limits the number of
CREATE2
calls to 1 when usinginitCode
meaning that for example, it is currently not possible to deploy a Safe using account abstraction with nothing but a WebAuthn signer.Proposed solution
The proposed solution would be to split validation into two phases:
validateUserOp
would:Alternatives
CREATE2
Calls From a Staked Factory #147Outcome
A script similar toAn E2E test using the reference bundler where an account can execute a user operation and be deployed as part of the single bundle while using a singleton signer.runOp
where an owner can be deployed with the account as part of the single bundle.The focus is not to have a useful signer contract, just a process that is supported under 4337.
The text was updated successfully, but these errors were encountered: