@@ -11,18 +11,18 @@ library AccountPermissionsStorage {
11
11
bytes32 public constant ACCOUNT_PERMISSIONS_STORAGE_POSITION = keccak256 ("account.permissions.storage " );
12
12
13
13
struct Data {
14
+ /// @dev The set of all admins of the wallet.
15
+ EnumerableSet.AddressSet allAdmins;
16
+ /// @dev The set of all signers with permission to use the account.
17
+ EnumerableSet.AddressSet allSigners;
14
18
/// @dev Map from address => whether the address is an admin.
15
19
mapping (address => bool ) isAdmin;
16
- /// @dev Map from keccak256 hash of a role => active restrictions for that role .
17
- mapping (bytes32 => IAccountPermissions.RoleStatic) roleRestrictions ;
18
- /// @dev Map from address => the role held by that address .
19
- mapping (address => bytes32 ) roleOfAccount ;
20
+ /// @dev Map from signer address => active restrictions for that signer .
21
+ mapping (address => IAccountPermissions.SignerPermissionsStatic) signerPermissions ;
22
+ /// @dev Map from signer address => approved target the signer can call using the account contract .
23
+ mapping (address => EnumerableSet.AddressSet) approvedTargets ;
20
24
/// @dev Mapping from a signed request UID => whether the request is processed.
21
25
mapping (bytes32 => bool ) executed;
22
- /// @dev Map from keccak256 hash of a role to its approved targets.
23
- mapping (bytes32 => EnumerableSet.AddressSet) approvedTargets;
24
- /// @dev map from keccak256 hash of a role to its members' data. See {RoleMembers}.
25
- mapping (bytes32 => EnumerableSet.AddressSet) roleMembers;
26
26
}
27
27
28
28
function accountPermissionsStorage () internal pure returns (Data storage accountPermissionsData ) {
@@ -39,7 +39,7 @@ abstract contract AccountPermissions is IAccountPermissions, EIP712 {
39
39
40
40
bytes32 private constant TYPEHASH =
41
41
keccak256 (
42
- "RoleRequest(bytes32 role ,address target,uint8 action ,uint128 validityStartTimestamp ,uint128 validityEndTimestamp ,bytes32 uid) "
42
+ "SignerPermissionRequest(address signer ,address[] approvedTargets,uint256 nativeTokenLimitPerTransaction ,uint128 permissionStartTimestamp ,uint128 permissionEndTimestamp,uint128 reqValidityStartTimestamp,uint128 reqValidityEndTimestamp ,bytes32 uid) "
43
43
);
44
44
45
45
modifier onlyAdmin () virtual {
@@ -56,61 +56,45 @@ abstract contract AccountPermissions is IAccountPermissions, EIP712 {
56
56
_setAdmin (_account, _isAdmin);
57
57
}
58
58
59
- /// @notice Sets the restrictions for a given role.
60
- function setRoleRestrictions (RoleRestrictions calldata _restrictions ) external virtual onlyAdmin {
61
- bytes32 role = _restrictions.role;
59
+ /// @notice Sets the permissions for a given signer.
60
+ function setPermissionsForSigner (SignerPermissionRequest calldata _req , bytes calldata _signature ) external {
61
+ address targetSigner = _req.signer;
62
+ require (! isAdmin (targetSigner), "AccountPermissions: signer is already an admin " );
62
63
63
- require (role != bytes32 (0 ), "AccountPermissions: role cannot be empty " );
64
+ require (
65
+ _req.reqValidityStartTimestamp <= block .timestamp && block .timestamp < _req.reqValidityEndTimestamp,
66
+ "AccountPermissions: invalid request validity period "
67
+ );
68
+
69
+ (bool success , address signer ) = verifySignerPermissionRequest (_req, _signature);
70
+ require (success, "AccountPermissions: invalid signature " );
64
71
65
72
AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
66
- data.roleRestrictions[role] = RoleStatic (
67
- role,
68
- _restrictions.maxValuePerTransaction,
69
- _restrictions.startTimestamp,
70
- _restrictions.endTimestamp
73
+
74
+ data.allSigners.add (targetSigner);
75
+ data.executed[_req.uid] = true ;
76
+
77
+ data.signerPermissions[targetSigner] = SignerPermissionsStatic (
78
+ _req.nativeTokenLimitPerTransaction,
79
+ _req.permissionStartTimestamp,
80
+ _req.permissionEndTimestamp
71
81
);
72
82
73
- address [] memory currentTargets = data.approvedTargets[role ].values ();
83
+ address [] memory currentTargets = data.approvedTargets[targetSigner ].values ();
74
84
uint256 currentLen = currentTargets.length ;
75
85
76
86
for (uint256 i = 0 ; i < currentLen; i += 1 ) {
77
- data.approvedTargets[role ].remove (currentTargets[i]);
87
+ data.approvedTargets[targetSigner ].remove (currentTargets[i]);
78
88
}
79
89
80
- uint256 len = _restrictions .approvedTargets.length ;
90
+ uint256 len = _req .approvedTargets.length ;
81
91
for (uint256 i = 0 ; i < len; i += 1 ) {
82
- data.approvedTargets[role ].add (_restrictions .approvedTargets[i]);
92
+ data.approvedTargets[targetSigner ].add (_req .approvedTargets[i]);
83
93
}
84
94
85
- emit RoleUpdated (_restrictions.role, _restrictions);
86
- }
87
-
88
- /// @notice Grant / revoke a role from a given signer.
89
- function changeRole (RoleRequest calldata _req , bytes calldata _signature ) external virtual {
90
- require (_req.role != bytes32 (0 ), "AccountPermissions: role cannot be empty " );
91
- require (
92
- _req.validityStartTimestamp < block .timestamp && block .timestamp < _req.validityEndTimestamp,
93
- "AccountPermissions: invalid validity period "
94
- );
95
-
96
- (bool success , address signer ) = verifyRoleRequest (_req, _signature);
95
+ _afterSignerPermissionsUpdate (_req);
97
96
98
- require (success, "AccountPermissions: invalid signature " );
99
-
100
- AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
101
- data.executed[_req.uid] = true ;
102
-
103
- if (_req.action == RoleAction.GRANT) {
104
- data.roleOfAccount[_req.target] = _req.role;
105
- data.roleMembers[_req.role].add (_req.target);
106
- } else {
107
- delete data.roleOfAccount[_req.target];
108
- data.roleMembers[_req.role].remove (_req.target);
109
- }
110
-
111
- emit RoleAssignment (_req.role, _req.target, signer, _req);
112
-
113
- _afterChangeRole (_req);
97
+ emit SignerPermissionsUpdated (signer, targetSigner, _req);
114
98
}
115
99
116
100
/*///////////////////////////////////////////////////////////////
@@ -123,45 +107,34 @@ abstract contract AccountPermissions is IAccountPermissions, EIP712 {
123
107
return data.isAdmin[_account];
124
108
}
125
109
126
- /// @notice Returns the role held by a given account along with its restrictions .
127
- function getRoleRestrictionsForAccount (address _account ) external view virtual returns (RoleRestrictions memory ) {
110
+ /// @notice Returns whether the given account is an active signer on the account .
111
+ function isActiveSigner (address signer ) public view returns (bool ) {
128
112
AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
129
- bytes32 role = data.roleOfAccount[_account];
130
- RoleStatic memory roleRestrictions = data.roleRestrictions[role];
113
+ SignerPermissionsStatic memory permissions = data.signerPermissions[signer];
131
114
132
115
return
133
- RoleRestrictions (
134
- role,
135
- data.approvedTargets[role].values (),
136
- roleRestrictions.maxValuePerTransaction,
137
- roleRestrictions.startTimestamp,
138
- roleRestrictions.endTimestamp
139
- );
116
+ permissions.startTimestamp <= block .timestamp &&
117
+ block .timestamp < permissions.endTimestamp &&
118
+ data.approvedTargets[signer].length () > 0 ;
140
119
}
141
120
142
- /// @notice Returns the role restrictions for a given role .
143
- function getRoleRestrictions ( bytes32 _role ) external view virtual returns (RoleRestrictions memory ) {
121
+ /// @notice Returns the restrictions under which a signer can use the smart wallet .
122
+ function getPermissionsForSigner ( address signer ) external view returns (SignerPermissions memory ) {
144
123
AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
145
- RoleStatic memory roleRestrictions = data.roleRestrictions[_role ];
124
+ SignerPermissionsStatic memory permissions = data.signerPermissions[signer ];
146
125
147
126
return
148
- RoleRestrictions (
149
- _role ,
150
- data.approvedTargets[_role ].values (),
151
- roleRestrictions.maxValuePerTransaction ,
152
- roleRestrictions .startTimestamp,
153
- roleRestrictions .endTimestamp
127
+ SignerPermissions (
128
+ signer ,
129
+ data.approvedTargets[signer ].values (),
130
+ permissions.nativeTokenLimitPerTransaction ,
131
+ permissions .startTimestamp,
132
+ permissions .endTimestamp
154
133
);
155
134
}
156
135
157
- /// @notice Returns all accounts that have a role.
158
- function getAllRoleMembers (bytes32 _role ) external view virtual returns (address [] memory ) {
159
- AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
160
- return data.roleMembers[_role].values ();
161
- }
162
-
163
136
/// @dev Verifies that a request is signed by an authorized account.
164
- function verifyRoleRequest (RoleRequest calldata req , bytes calldata signature )
137
+ function verifySignerPermissionRequest (SignerPermissionRequest calldata req , bytes calldata signature )
165
138
public
166
139
view
167
140
virtual
@@ -172,23 +145,94 @@ abstract contract AccountPermissions is IAccountPermissions, EIP712 {
172
145
success = ! data.executed[req.uid] && isAdmin (signer);
173
146
}
174
147
148
+ /// @notice Returns all active and inactive signers of the account.
149
+ function getAllSigners () external view returns (SignerPermissions[] memory signers ) {
150
+ AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
151
+ address [] memory allSigners = data.allSigners.values ();
152
+
153
+ uint256 len = allSigners.length ;
154
+ signers = new SignerPermissions [](len);
155
+ for (uint256 i = 0 ; i < len; i += 1 ) {
156
+ address signer = allSigners[i];
157
+ SignerPermissionsStatic memory permissions = data.signerPermissions[signer];
158
+
159
+ signers[i] = SignerPermissions (
160
+ signer,
161
+ data.approvedTargets[signer].values (),
162
+ permissions.nativeTokenLimitPerTransaction,
163
+ permissions.startTimestamp,
164
+ permissions.endTimestamp
165
+ );
166
+ }
167
+ }
168
+
169
+ /// @notice Returns all signers with active permissions to use the account.
170
+ function getAllActiveSigners () external view returns (SignerPermissions[] memory signers ) {
171
+ AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
172
+ address [] memory allSigners = data.allSigners.values ();
173
+
174
+ uint256 len = allSigners.length ;
175
+ uint256 numOfActiveSigners = 0 ;
176
+ bool [] memory isSignerActive = new bool [](len);
177
+
178
+ for (uint256 i = 0 ; i < len; i += 1 ) {
179
+ address signer = allSigners[i];
180
+
181
+ bool isActive = isActiveSigner (signer);
182
+ isSignerActive[i] = isActive;
183
+ if (isActive) {
184
+ numOfActiveSigners++ ;
185
+ }
186
+ }
187
+
188
+ signers = new SignerPermissions [](numOfActiveSigners);
189
+ uint256 index = 0 ;
190
+ for (uint256 i = 0 ; i < len; i += 1 ) {
191
+ if (! isSignerActive[i]) {
192
+ continue ;
193
+ }
194
+ address signer = allSigners[i];
195
+ SignerPermissionsStatic memory permissions = data.signerPermissions[signer];
196
+
197
+ signers[index++ ] = SignerPermissions (
198
+ signer,
199
+ data.approvedTargets[signer].values (),
200
+ permissions.nativeTokenLimitPerTransaction,
201
+ permissions.startTimestamp,
202
+ permissions.endTimestamp
203
+ );
204
+ }
205
+ }
206
+
207
+ /// @notice Returns all admins of the account.
208
+ function getAllAdmins () external view returns (address [] memory ) {
209
+ AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
210
+ return data.allAdmins.values ();
211
+ }
212
+
175
213
/*///////////////////////////////////////////////////////////////
176
214
Internal functions
177
215
//////////////////////////////////////////////////////////////*/
178
216
179
217
/// @notice Runs after every `changeRole` run.
180
- function _afterChangeRole (RoleRequest calldata _req ) internal virtual ;
218
+ function _afterSignerPermissionsUpdate (SignerPermissionRequest calldata _req ) internal virtual ;
181
219
182
220
/// @notice Makes the given account an admin.
183
221
function _setAdmin (address _account , bool _isAdmin ) internal virtual {
184
222
AccountPermissionsStorage.Data storage data = AccountPermissionsStorage.accountPermissionsStorage ();
185
223
data.isAdmin[_account] = _isAdmin;
186
224
225
+ if (_isAdmin) {
226
+ data.allAdmins.add (_account);
227
+ } else {
228
+ data.allAdmins.remove (_account);
229
+ }
230
+
187
231
emit AdminUpdated (_account, _isAdmin);
188
232
}
189
233
190
234
/// @dev Returns the address of the signer of the request.
191
- function _recoverAddress (RoleRequest calldata _req , bytes calldata _signature )
235
+ function _recoverAddress (SignerPermissionRequest calldata _req , bytes calldata _signature )
192
236
internal
193
237
view
194
238
virtual
@@ -198,15 +242,17 @@ abstract contract AccountPermissions is IAccountPermissions, EIP712 {
198
242
}
199
243
200
244
/// @dev Encodes a request for recovery of the signer in `recoverAddress`.
201
- function _encodeRequest (RoleRequest calldata _req ) internal pure virtual returns (bytes memory ) {
245
+ function _encodeRequest (SignerPermissionRequest calldata _req ) internal pure virtual returns (bytes memory ) {
202
246
return
203
247
abi.encode (
204
248
TYPEHASH,
205
- _req.role,
206
- _req.target,
207
- _req.action,
208
- _req.validityStartTimestamp,
209
- _req.validityEndTimestamp,
249
+ _req.signer,
250
+ _req.approvedTargets,
251
+ _req.nativeTokenLimitPerTransaction,
252
+ _req.permissionStartTimestamp,
253
+ _req.permissionEndTimestamp,
254
+ _req.reqValidityStartTimestamp,
255
+ _req.reqValidityEndTimestamp,
210
256
_req.uid
211
257
);
212
258
}
0 commit comments