@@ -7,6 +7,7 @@ import "../../openzeppelin-presets/proxy/Clones.sol";
77import "../../openzeppelin-presets/utils/structs/EnumerableSet.sol " ;
88import "../utils/BaseAccount.sol " ;
99import "../../extension/interface/IAccountPermissions.sol " ;
10+ import "../../lib/BytesLib.sol " ;
1011
1112// Interface
1213import "../interfaces/IEntrypoint.sol " ;
@@ -29,16 +30,19 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall {
2930 //////////////////////////////////////////////////////////////*/
3031
3132 address public immutable accountImplementation;
33+ address public immutable entrypoint;
3234
35+ EnumerableSet.AddressSet private allAccounts;
3336 mapping (address => EnumerableSet.AddressSet) internal accountsOfSigner;
3437 mapping (address => EnumerableSet.AddressSet) internal signersOfAccount;
3538
3639 /*///////////////////////////////////////////////////////////////
3740 Constructor
3841 //////////////////////////////////////////////////////////////*/
3942
40- constructor (address _accountImpl ) {
43+ constructor (address _accountImpl , address _entrypoint ) {
4144 accountImplementation = _accountImpl;
45+ entrypoint = _entrypoint;
4246 }
4347
4448 /*///////////////////////////////////////////////////////////////
@@ -57,18 +61,28 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall {
5761
5862 account = Clones.cloneDeterministic (impl, salt);
5963
64+ if (msg .sender != entrypoint) {
65+ require (allAccounts.add (account), "AccountFactory: account already registered " );
66+ }
67+
6068 _initializeAccount (account, _admin, _data);
6169
6270 emit AccountCreated (account, _admin);
6371
6472 return account;
6573 }
6674
67- /// @notice Callback function for an Account to register its signers .
68- function onSignerAdded ( address _signer ) external {
75+ /// @notice Callback function for an Account to register itself on the factory .
76+ function onRegister ( ) external {
6977 address account = msg .sender ;
78+ require (_isAccountOfFactory (account), "AccountFactory: not an account. " );
79+
80+ require (allAccounts.add (account), "AccountFactory: account already registered " );
81+ }
7082
71- require (account.code.length > 0 , "AccountFactory: not an account. " );
83+ function onSignerAdded (address _signer ) external {
84+ address account = msg .sender ;
85+ require (_isAccountOfFactory (account), "AccountFactory: not an account. " );
7286
7387 bool isAdmin = IAccountPermissions (account).isAdmin (_signer);
7488
@@ -94,8 +108,7 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall {
94108 /// @notice Callback function for an Account to un-register its signers.
95109 function onSignerRemoved (address _signer ) external {
96110 address account = msg .sender ;
97-
98- require (account.code.length > 0 , "AccountFactory: not an account. " );
111+ require (_isAccountOfFactory (account), "AccountFactory: not an account. " );
99112
100113 bool isAccount = accountsOfSigner[_signer].remove (account);
101114 bool isSigner = signersOfAccount[account].remove (_signer);
@@ -111,6 +124,16 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall {
111124 View functions
112125 //////////////////////////////////////////////////////////////*/
113126
127+ /// @notice Returns whether an account is registered on this factory.
128+ function isRegistered (address _account ) external view returns (bool ) {
129+ return allAccounts.contains (_account);
130+ }
131+
132+ /// @notice Returns all accounts created on the factory.
133+ function getAllAccounts () external view returns (address [] memory ) {
134+ return allAccounts.values ();
135+ }
136+
114137 /// @notice Returns the address of an Account that would be deployed with the given admin signer.
115138 function getAddress (address _adminSigner , bytes calldata _data ) public view returns (address ) {
116139 bytes32 salt = _generateSalt (_adminSigner, _data);
@@ -131,6 +154,17 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall {
131154 Internal functions
132155 //////////////////////////////////////////////////////////////*/
133156
157+ /// @dev Returns whether the caller is an account deployed by this factory.
158+ function _isAccountOfFactory (address _account ) internal view virtual returns (bool ) {
159+ address impl = _getImplementation (_account);
160+ return _account.code.length > 0 && impl == accountImplementation;
161+ }
162+
163+ function _getImplementation (address cloneAddress ) internal view returns (address ) {
164+ bytes memory code = cloneAddress.code;
165+ return BytesLib.toAddress (code, 10 );
166+ }
167+
134168 /// @dev Returns the salt used when deploying an Account.
135169 function _generateSalt (address _admin , bytes calldata ) internal view virtual returns (bytes32 ) {
136170 return keccak256 (abi.encode (_admin));
0 commit comments