Skip to content

Commit 105e734

Browse files
authored
Merge branch 'main' into erc721base-add-queryable
2 parents 125c8c0 + c7a4554 commit 105e734

23 files changed

+835
-161
lines changed

contracts/prebuilts/account/dynamic/DynamicAccount.sol

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,23 @@ contract DynamicAccount is AccountCore, BaseRouter {
2424
//////////////////////////////////////////////////////////////*/
2525

2626
constructor(IEntryPoint _entrypoint, Extension[] memory _defaultExtensions)
27-
AccountCore(_entrypoint, msg.sender)
27+
AccountCore(_entrypoint)
2828
BaseRouter(_defaultExtensions)
2929
{
3030
_disableInitializers();
3131
}
3232

3333
/// @notice Initializes the smart contract wallet.
34-
function initialize(address _defaultAdmin, bytes calldata) public override initializer {
34+
function initialize(
35+
address _defaultAdmin,
36+
address _factory,
37+
bytes calldata _data
38+
) public override initializer {
3539
__BaseRouter_init();
36-
AccountCoreStorage.data().firstAdmin = _defaultAdmin;
40+
41+
// This is passed as data in the `_registerOnFactory()` call in `AccountExtension` / `Account`.
42+
AccountCoreStorage.data().creationSalt = _generateSalt(_defaultAdmin, _data);
43+
AccountCoreStorage.data().factory = _factory;
3744
_setAdmin(_defaultAdmin, true);
3845
}
3946

contracts/prebuilts/account/dynamic/DynamicAccountFactory.sol

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ pragma solidity ^0.8.12;
44
// Utils
55
import "../utils/BaseAccountFactory.sol";
66
import "@thirdweb-dev/dynamic-contracts/src/interface/IExtension.sol";
7+
import "../../../extension/upgradeable/Initializable.sol";
78

89
// Extensions
9-
import "../../../extension/upgradeable//PermissionsEnumerable.sol";
10-
import "../../../extension/upgradeable//ContractMetadata.sol";
10+
import "../../../extension/upgradeable/PermissionsEnumerable.sol";
11+
import "../../../extension/upgradeable/ContractMetadata.sol";
1112

1213
// Smart wallet implementation
1314
import { DynamicAccount, IEntryPoint } from "./DynamicAccount.sol";
@@ -21,20 +22,26 @@ import { DynamicAccount, IEntryPoint } from "./DynamicAccount.sol";
2122
// \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ |
2223
// \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/
2324

24-
contract DynamicAccountFactory is BaseAccountFactory, ContractMetadata, PermissionsEnumerable {
25+
contract DynamicAccountFactory is Initializable, BaseAccountFactory, ContractMetadata, PermissionsEnumerable {
2526
address public constant ENTRYPOINT_ADDRESS = 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789;
2627

2728
/*///////////////////////////////////////////////////////////////
2829
Constructor
2930
//////////////////////////////////////////////////////////////*/
3031

31-
constructor(address _defaultAdmin, IExtension.Extension[] memory _defaultExtensions)
32+
constructor(IExtension.Extension[] memory _defaultExtensions)
3233
BaseAccountFactory(
33-
payable(address(new DynamicAccount(IEntryPoint(ENTRYPOINT_ADDRESS), _defaultExtensions))),
34+
address(new DynamicAccount(IEntryPoint(ENTRYPOINT_ADDRESS), _defaultExtensions)),
3435
ENTRYPOINT_ADDRESS
3536
)
3637
{
38+
_disableInitializers();
39+
}
40+
41+
/// @notice Initializes the factory contract.
42+
function initialize(address _defaultAdmin, string memory _contractURI) external initializer {
3743
_setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
44+
_setupContractURI(_contractURI);
3845
}
3946

4047
/*///////////////////////////////////////////////////////////////
@@ -47,7 +54,7 @@ contract DynamicAccountFactory is BaseAccountFactory, ContractMetadata, Permissi
4754
address _admin,
4855
bytes calldata _data
4956
) internal override {
50-
DynamicAccount(payable(_account)).initialize(_admin, _data);
57+
DynamicAccount(payable(_account)).initialize(_admin, address(this), _data);
5158
}
5259

5360
/// @dev Returns whether contract metadata can be set in the given execution context.

contracts/prebuilts/account/interface/IAccountFactory.sol

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,8 @@ interface IAccountFactory is IAccountFactoryCore {
99
//////////////////////////////////////////////////////////////*/
1010

1111
/// @notice Callback function for an Account to register its signers.
12-
function onSignerAdded(
13-
address signer,
14-
address creatorAdmin,
15-
bytes memory data
16-
) external;
12+
function onSignerAdded(address signer, bytes32 salt) external;
1713

1814
/// @notice Callback function for an Account to un-register its signers.
19-
function onSignerRemoved(
20-
address signer,
21-
address creatorAdmin,
22-
bytes memory data
23-
) external;
15+
function onSignerRemoved(address signer, bytes32 salt) external;
2416
}

contracts/prebuilts/account/managed/ManagedAccount.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ import "@thirdweb-dev/dynamic-contracts/src/core/Router.sol";
1919
import "@thirdweb-dev/dynamic-contracts/src/interface/IRouterState.sol";
2020

2121
contract ManagedAccount is AccountCore, Router, IRouterState {
22-
constructor(IEntryPoint _entrypoint, address _factory) AccountCore(_entrypoint, _factory) {}
22+
constructor(IEntryPoint _entrypoint) AccountCore(_entrypoint) {}
2323

2424
/// @notice Returns the implementation contract address for a given function signature.
2525
function getImplementationForFunction(bytes4 _functionSelector) public view virtual override returns (address) {
26-
return Router(payable(factory)).getImplementationForFunction(_functionSelector);
26+
return Router(payable(AccountCoreStorage.data().factory)).getImplementationForFunction(_functionSelector);
2727
}
2828

2929
/// @notice Returns all extensions of the Router.
3030
function getAllExtensions() external view returns (Extension[] memory) {
31-
return IRouterState(payable(factory)).getAllExtensions();
31+
return IRouterState(payable(AccountCoreStorage.data().factory)).getAllExtensions();
3232
}
3333
}

contracts/prebuilts/account/managed/ManagedAccountFactory.sol

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity ^0.8.12;
44
// Utils
55
import "@thirdweb-dev/dynamic-contracts/src/presets/BaseRouter.sol";
66
import "../utils/BaseAccountFactory.sol";
7+
import "../../../extension/upgradeable/Initializable.sol";
78

89
// Extensions
910
import "../../../extension/upgradeable//PermissionsEnumerable.sol";
@@ -21,25 +22,35 @@ import { ManagedAccount, IEntryPoint } from "./ManagedAccount.sol";
2122
// \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ |
2223
// \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/
2324

24-
contract ManagedAccountFactory is BaseAccountFactory, ContractMetadata, PermissionsEnumerable, BaseRouter {
25+
contract ManagedAccountFactory is
26+
Initializable,
27+
BaseAccountFactory,
28+
ContractMetadata,
29+
PermissionsEnumerable,
30+
BaseRouter
31+
{
2532
/*///////////////////////////////////////////////////////////////
2633
Constructor
2734
//////////////////////////////////////////////////////////////*/
2835

29-
constructor(
30-
address _defaultAdmin,
31-
IEntryPoint _entrypoint,
32-
Extension[] memory _defaultExtensions
33-
)
36+
constructor(IEntryPoint _entrypoint, Extension[] memory _defaultExtensions)
3437
BaseRouter(_defaultExtensions)
35-
BaseAccountFactory(payable(address(new ManagedAccount(_entrypoint, address(this)))), address(_entrypoint))
38+
BaseAccountFactory(address(new ManagedAccount(_entrypoint)), address(_entrypoint))
3639
{
40+
_disableInitializers();
41+
}
42+
43+
/// @notice Initializes the factory contract.
44+
function initialize(address _defaultAdmin, string memory _contractURI) external initializer {
3745
__BaseRouter_init();
46+
3847
_setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
3948

4049
bytes32 _extensionRole = keccak256("EXTENSION_ROLE");
4150
_setupRole(_extensionRole, _defaultAdmin);
4251
_setRoleAdmin(_extensionRole, _extensionRole);
52+
53+
_setupContractURI(_contractURI);
4354
}
4455

4556
/*///////////////////////////////////////////////////////////////
@@ -52,7 +63,7 @@ contract ManagedAccountFactory is BaseAccountFactory, ContractMetadata, Permissi
5263
address _admin,
5364
bytes calldata _data
5465
) internal override {
55-
ManagedAccount(payable(_account)).initialize(_admin, _data);
66+
ManagedAccount(payable(_account)).initialize(_admin, address(this), _data);
5667
}
5768

5869
/// @dev Returns whether all relevant permission and other checks are met before any upgrade.

contracts/prebuilts/account/non-upgradeable/Account.sol

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ contract Account is AccountCore, ContractMetadata, ERC1271, ERC721Holder, ERC115
3333
using ECDSA for bytes32;
3434
using EnumerableSet for EnumerableSet.AddressSet;
3535

36+
bytes32 private constant MSG_TYPEHASH = keccak256("AccountMessage(bytes message)");
37+
3638
/*///////////////////////////////////////////////////////////////
3739
Constructor, Initializer, Modifiers
3840
//////////////////////////////////////////////////////////////*/
3941

40-
constructor(IEntryPoint _entrypoint, address _factory) AccountCore(_entrypoint, _factory) {}
42+
constructor(IEntryPoint _entrypoint) AccountCore(_entrypoint) {}
4143

4244
/// @notice Checks whether the caller is the EntryPoint contract or the admin.
4345
modifier onlyAdminOrEntrypoint() virtual {
@@ -61,14 +63,15 @@ contract Account is AccountCore, ContractMetadata, ERC1271, ERC721Holder, ERC115
6163
}
6264

6365
/// @notice See EIP-1271
64-
function isValidSignature(bytes32 _hash, bytes memory _signature)
66+
function isValidSignature(bytes32 _message, bytes memory _signature)
6567
public
6668
view
6769
virtual
6870
override
6971
returns (bytes4 magicValue)
7072
{
71-
address signer = _hash.recover(_signature);
73+
bytes32 messageHash = getMessageHash(abi.encode(_message));
74+
address signer = messageHash.recover(_signature);
7275

7376
if (isAdmin(signer)) {
7477
return MAGICVALUE;
@@ -87,6 +90,16 @@ contract Account is AccountCore, ContractMetadata, ERC1271, ERC721Holder, ERC115
8790
}
8891
}
8992

93+
/**
94+
* @notice Returns the hash of message that should be signed for EIP1271 verification.
95+
* @param message Message to be hashed i.e. `keccak256(abi.encode(data))`
96+
* @return Hashed message
97+
*/
98+
function getMessageHash(bytes memory message) public view returns (bytes32) {
99+
bytes32 messageHash = keccak256(abi.encode(MSG_TYPEHASH, keccak256(message)));
100+
return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), messageHash));
101+
}
102+
90103
/*///////////////////////////////////////////////////////////////
91104
External functions
92105
//////////////////////////////////////////////////////////////*/
@@ -115,15 +128,26 @@ contract Account is AccountCore, ContractMetadata, ERC1271, ERC721Holder, ERC115
115128
}
116129
}
117130

131+
/// @notice Deposit funds for this account in Entrypoint.
132+
function addDeposit() public payable {
133+
entryPoint().depositTo{ value: msg.value }(address(this));
134+
}
135+
136+
/// @notice Withdraw funds for this account from Entrypoint.
137+
function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public {
138+
_onlyAdmin();
139+
entryPoint().withdrawTo(withdrawAddress, amount);
140+
}
141+
118142
/*///////////////////////////////////////////////////////////////
119143
Internal functions
120144
//////////////////////////////////////////////////////////////*/
121145

122146
/// @dev Registers the account on the factory if it hasn't been registered yet.
123147
function _registerOnFactory() internal virtual {
124-
BaseAccountFactory factoryContract = BaseAccountFactory(factory);
148+
BaseAccountFactory factoryContract = BaseAccountFactory(AccountCoreStorage.data().factory);
125149
if (!factoryContract.isRegistered(address(this))) {
126-
factoryContract.onRegister(AccountCoreStorage.data().firstAdmin, "");
150+
factoryContract.onRegister(AccountCoreStorage.data().creationSalt);
127151
}
128152
}
129153

contracts/prebuilts/account/non-upgradeable/AccountFactory.sol

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pragma solidity ^0.8.12;
55
import "../utils/BaseAccountFactory.sol";
66
import "../utils/BaseAccount.sol";
77
import "../../../external-deps/openzeppelin/proxy/Clones.sol";
8+
import "../../../extension/upgradeable/Initializable.sol";
89

910
// Extensions
1011
import "../../../extension/upgradeable//PermissionsEnumerable.sol";
@@ -25,15 +26,19 @@ import { Account } from "./Account.sol";
2526
// \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ |
2627
// \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/
2728

28-
contract AccountFactory is BaseAccountFactory, ContractMetadata, PermissionsEnumerable {
29+
contract AccountFactory is Initializable, BaseAccountFactory, ContractMetadata, PermissionsEnumerable {
2930
/*///////////////////////////////////////////////////////////////
3031
Constructor
3132
//////////////////////////////////////////////////////////////*/
3233

33-
constructor(address _defaultAdmin, IEntryPoint _entrypoint)
34-
BaseAccountFactory(address(new Account(_entrypoint, address(this))), address(_entrypoint))
35-
{
34+
constructor(IEntryPoint _entrypoint) BaseAccountFactory(address(new Account(_entrypoint)), address(_entrypoint)) {
35+
_disableInitializers();
36+
}
37+
38+
/// @notice Initializes the factory contract.
39+
function initialize(address _defaultAdmin, string memory _contractURI) external initializer {
3640
_setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
41+
_setupContractURI(_contractURI);
3742
}
3843

3944
/*///////////////////////////////////////////////////////////////
@@ -46,7 +51,7 @@ contract AccountFactory is BaseAccountFactory, ContractMetadata, PermissionsEnum
4651
address _admin,
4752
bytes calldata _data
4853
) internal override {
49-
Account(payable(_account)).initialize(_admin, _data);
54+
Account(payable(_account)).initialize(_admin, address(this), _data);
5055
}
5156

5257
/// @dev Returns whether contract metadata can be set in the given execution context.

0 commit comments

Comments
 (0)