Skip to content

Commit a1d07fe

Browse files
committed
Improve docs
1 parent c33ca98 commit a1d07fe

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// contracts/MyAccount.sol
2+
// SPDX-License-Identifier: MIT
3+
4+
pragma solidity ^0.8.20;
5+
6+
import {Account} from "../../../account/Account.sol";
7+
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
8+
import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
9+
import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
10+
import {ERC7739} from "../../../utils/cryptography/ERC7739.sol";
11+
import {ERC7821} from "../../../account/extensions/ERC7821.sol";
12+
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
13+
import {SignerERC7913} from "../../../utils/cryptography/SignerERC7913.sol";
14+
15+
contract MyAccount7913 is Account, SignerERC7913, ERC7739, ERC7821, ERC721Holder, ERC1155Holder, Initializable {
16+
constructor() EIP712("MyAccount7913", "1") {}
17+
18+
function initialize(bytes memory signer) public initializer {
19+
_setSigner(signer);
20+
}
21+
22+
/// @dev Allows the entry point as an authorized executor.
23+
function _erc7821AuthorizedExecutor(
24+
address caller,
25+
bytes32 mode,
26+
bytes calldata executionData
27+
) internal view virtual override returns (bool) {
28+
return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
29+
}
30+
}

contracts/utils/cryptography/SignerERC7913.sol

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,44 @@ import {AbstractSigner} from "./AbstractSigner.sol";
66
import {ERC7913Utils} from "./ERC7913Utils.sol";
77

88
/**
9-
* @dev Implementation of {AbstractSigner} that supports ERC-7913 signers.
9+
* @dev Implementation of {AbstractSigner} using
10+
* https://eips.ethereum.org/EIPS/eip-7913[ERC-7913] signature verification.
1011
*
11-
* For {Account} usage, an {_setSigner} function is provided to set the ERC-7913 formatted {signer}.
12-
* Doing so it's easier for a factory, whose likely to use initializable clones of this contract.
12+
* For {Account} usage, a {_setSigner} function is provided to set the ERC-7913 formatted {signer}.
13+
* Doing so is easier for a factory, who is likely to use initializable clones of this contract.
14+
*
15+
* The signer is a `bytes` object that concatenates a verifier address and a key: `verifier || key`.
1316
*
1417
* Example of usage:
1518
*
1619
* ```solidity
1720
* contract MyAccountERC7913 is Account, SignerERC7913, Initializable {
1821
* constructor() EIP712("MyAccountERC7913", "1") {}
1922
*
20-
* function initialize(bytes memory signer) public initializer {
21-
* _setSigner(signer);
23+
* function initialize(bytes memory signer_) public initializer {
24+
* _setSigner(signer_);
2225
* }
2326
* }
2427
* ```
2528
*
26-
* IMPORTANT: Avoiding to call {_setSigner} either during construction (if used standalone)
29+
* IMPORTANT: Failing to call {_setSigner} either during construction (if used standalone)
2730
* or during initialization (if used as a clone) may leave the signer either front-runnable or unusable.
2831
*/
2932

3033
abstract contract SignerERC7913 is AbstractSigner {
3134
bytes private _signer;
3235

36+
/// @dev Sets the signer (i.e. `verifier || key`) with an ERC-7913 formatted signer.
3337
function _setSigner(bytes memory signer_) internal {
3438
_signer = signer_;
3539
}
3640

41+
/// @dev Return the ERC-7913 signer (i.e. `verifier || key`).
3742
function signer() public view virtual returns (bytes memory) {
3843
return _signer;
3944
}
4045

41-
/// @inheritdoc AbstractSigner
46+
/// @dev Verifies a signature using {ERC7913Utils.isValidSignatureNow} with {signer}, `hash` and `signature`.
4247
function _rawSignatureValidation(
4348
bytes32 hash,
4449
bytes calldata signature

docs/modules/ROOT/pages/account-abstraction.adoc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ To setup an account, you can either bring your own validation logic and start wi
2929

3030
=== Selecting a signer
3131

32-
The library includes specializations of the `AbstractSigner` contract that use custom digital signature verification algorithms. These are xref:api:utils.adoc#SignerECDSA[`SignerECDSA`], xref:api:utils.adoc#SignerP256[`SignerP256`] and xref:api:utils.adoc#SignerRSA[`SignerRSA`].
32+
The library includes specializations of the `AbstractSigner` contract that use custom digital signature verification algorithms. These are xref:api:utils.adoc#SignerECDSA[`SignerECDSA`], xref:api:utils.adoc#SignerP256[`SignerP256`], xref:api:utils.adoc#SignerRSA[`SignerRSA`], xref:api:utils.adoc#SignerERC7702[`SignerERC7702`], and xref:api:utils.adoc#SignerERC7913[`SignerERC7913`].
3333

3434
Since smart accounts are deployed by a factory, the best practice is to create https://docs.openzeppelin.com/contracts/5.x/api/proxy#minimal_clones[minimal clones] of initializable contracts. These signer implementations provide an initializable design by default so that the factory can interact with the account to set it up after deployment in a single transaction.
3535

@@ -56,6 +56,13 @@ Similarly, some government and corporate public key infrastructures use RSA for
5656
include::api:example$account/MyAccountRSA.sol[]
5757
----
5858

59+
For more advanced use cases where you need to support keys that don't have their own Ethereum address (like hardware devices or non-Ethereum cryptographic curves), you can use xref:api:utils.adoc#SignerERC7913[`SignerERC7913`]. This implementation allows for signature verification using ERC-7913 compatible verifiers.
60+
61+
[source,solidity]
62+
----
63+
include::api:example$account/MyAccountERC7913.sol[]
64+
----
65+
5966
== Account Factory
6067

6168
The first time a user sends an user operation, the account will be created deterministically (i.e. its code and address can be predicted) using the the `initCode` field in the UserOperation. This field contains both the address of a smart contract (the factory) and the data required to call it and deploy the smart account.

0 commit comments

Comments
 (0)