@@ -76,19 +76,21 @@ contract AccountCore is IAccountCore, Initializable, Multicall, BaseAccount, Acc
76
76
}
77
77
78
78
/// @notice Returns whether a signer is authorized to perform transactions using the wallet.
79
+ /* solhint-disable*/
79
80
function isValidSigner (address _signer , UserOperation calldata _userOp ) public view virtual returns (bool ) {
80
81
// First, check if the signer is an admin.
81
82
if (_accountPermissionsStorage ().isAdmin[_signer]) {
82
83
return true ;
83
84
}
84
85
85
86
SignerPermissionsStatic memory permissions = _accountPermissionsStorage ().signerPermissions[_signer];
87
+ EnumerableSet.AddressSet storage approvedTargets = _accountPermissionsStorage ().approvedTargets[_signer];
86
88
87
89
// If not an admin, check if the signer is active.
88
90
if (
89
91
permissions.startTimestamp > block .timestamp ||
90
92
block .timestamp >= permissions.endTimestamp ||
91
- _accountPermissionsStorage (). approvedTargets[_signer] .length () == 0
93
+ approvedTargets.length () == 0
92
94
) {
93
95
// Account: no active permissions.
94
96
return false ;
@@ -97,28 +99,44 @@ contract AccountCore is IAccountCore, Initializable, Multicall, BaseAccount, Acc
97
99
// Extract the function signature from the userOp calldata and check whether the signer is attempting to call `execute` or `executeBatch`.
98
100
bytes4 sig = getFunctionSignature (_userOp.callData);
99
101
102
+ // if address(0) is the only approved target, set isWildCard to true (wildcard approved).
103
+ bool isWildCard = approvedTargets.length () == 1 && approvedTargets.at (0 ) == address (0 );
104
+
100
105
if (sig == AccountExtension.execute.selector ) {
101
106
// Extract the `target` and `value` arguments from the calldata for `execute`.
102
107
(address target , uint256 value ) = decodeExecuteCalldata (_userOp.callData);
103
108
109
+ // if wildcard target is not approved, check that the target is in the approvedTargets set.
110
+ if (! isWildCard) {
111
+ // Check if the target is approved.
112
+ if (! approvedTargets.contains (target)) {
113
+ // Account: target not approved.
114
+ return false ;
115
+ }
116
+ }
117
+
104
118
// Check if the value is within the allowed range and if the target is approved.
105
- if (
106
- permissions.nativeTokenLimitPerTransaction < value ||
107
- ! _accountPermissionsStorage ().approvedTargets[_signer].contains (target)
108
- ) {
119
+ if (permissions.nativeTokenLimitPerTransaction < value) {
109
120
// Account: value too high OR Account: target not approved.
110
121
return false ;
111
122
}
112
123
} else if (sig == AccountExtension.executeBatch.selector ) {
113
124
// Extract the `target` and `value` array arguments from the calldata for `executeBatch`.
114
125
(address [] memory targets , uint256 [] memory values , ) = decodeExecuteBatchCalldata (_userOp.callData);
115
126
127
+ // if wildcard target is not approved, check that the targets are in the approvedTargets set.
128
+ if (! isWildCard) {
129
+ for (uint256 i = 0 ; i < targets.length ; i++ ) {
130
+ if (! approvedTargets.contains (targets[i])) {
131
+ // If any target is not approved, break the loop.
132
+ return false ;
133
+ }
134
+ }
135
+ }
136
+
116
137
// For each target+value pair, check if the value is within the allowed range and if the target is approved.
117
138
for (uint256 i = 0 ; i < targets.length ; i++ ) {
118
- if (
119
- permissions.nativeTokenLimitPerTransaction < values[i] ||
120
- ! _accountPermissionsStorage ().approvedTargets[_signer].contains (targets[i])
121
- ) {
139
+ if (permissions.nativeTokenLimitPerTransaction < values[i]) {
122
140
// Account: value too high OR Account: target not approved.
123
141
return false ;
124
142
}
@@ -131,6 +149,8 @@ contract AccountCore is IAccountCore, Initializable, Multicall, BaseAccount, Acc
131
149
return true ;
132
150
}
133
151
152
+ /* solhint-enable */
153
+
134
154
/*///////////////////////////////////////////////////////////////
135
155
External functions
136
156
//////////////////////////////////////////////////////////////*/
@@ -141,12 +161,14 @@ contract AccountCore is IAccountCore, Initializable, Multicall, BaseAccount, Acc
141
161
}
142
162
143
163
/// @notice Withdraw funds for this account from Entrypoint.
144
- function withdrawDepositTo (address payable withdrawAddress , uint256 amount ) public onlyAdmin {
164
+ function withdrawDepositTo (address payable withdrawAddress , uint256 amount ) public {
165
+ _onlyAdmin ();
145
166
entryPoint ().withdrawTo (withdrawAddress, amount);
146
167
}
147
168
148
169
/// @notice Overrides the Entrypoint contract being used.
149
- function setEntrypointOverride (IEntryPoint _entrypointOverride ) public virtual onlyAdmin {
170
+ function setEntrypointOverride (IEntryPoint _entrypointOverride ) public virtual {
171
+ _onlyAdmin ();
150
172
AccountCoreStorage.data ().entrypointOverride = address (_entrypointOverride);
151
173
}
152
174
@@ -195,8 +217,10 @@ contract AccountCore is IAccountCore, Initializable, Multicall, BaseAccount, Acc
195
217
196
218
if (! isValidSigner (signer, userOp)) return SIG_VALIDATION_FAILED;
197
219
198
- uint48 validAfter = uint48 (_accountPermissionsStorage ().signerPermissions[signer].startTimestamp);
199
- uint48 validUntil = uint48 (_accountPermissionsStorage ().signerPermissions[signer].endTimestamp);
220
+ SignerPermissionsStatic memory permissions = _accountPermissionsStorage ().signerPermissions[signer];
221
+
222
+ uint48 validAfter = uint48 (permissions.startTimestamp);
223
+ uint48 validUntil = uint48 (permissions.endTimestamp);
200
224
201
225
return _packValidationData (ValidationData (address (0 ), validAfter, validUntil));
202
226
}
0 commit comments