@@ -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