1
- // SPDX-License-Identifier: GPL-3.0
1
+ // SPDX-License-Identifier: MIT
2
2
pragma solidity ^ 0.8.23 ;
3
3
4
4
/* solhint-disable avoid-low-level-calls */
5
5
/* solhint-disable no-empty-blocks */
6
+ /* solhint-disable no-inline-assembly */
6
7
7
8
import "../interfaces/IAccount.sol " ;
8
9
import "../interfaces/IEntryPoint.sol " ;
10
+ import "../utils/Exec.sol " ;
9
11
import "./UserOperationLib.sol " ;
10
12
11
13
/**
@@ -16,6 +18,14 @@ import "./UserOperationLib.sol";
16
18
abstract contract BaseAccount is IAccount {
17
19
using UserOperationLib for PackedUserOperation;
18
20
21
+ struct Call {
22
+ address target;
23
+ uint256 value;
24
+ bytes data;
25
+ }
26
+
27
+ error ExecuteError (uint256 index , bytes error );
28
+
19
29
/**
20
30
* Return the account nonce.
21
31
* This method returns the next sequential nonce.
@@ -31,6 +41,40 @@ abstract contract BaseAccount is IAccount {
31
41
*/
32
42
function entryPoint () public view virtual returns (IEntryPoint);
33
43
44
+ /**
45
+ * execute a single call from the account.
46
+ */
47
+ function execute (address target , uint256 value , bytes calldata data ) virtual external {
48
+ _requireForExecute ();
49
+
50
+ bool ok = Exec.call (target, value, data, gasleft ());
51
+ if (! ok) {
52
+ Exec.revertWithReturnData ();
53
+ }
54
+ }
55
+
56
+ /**
57
+ * execute a batch of calls.
58
+ * revert on the first call that fails.
59
+ * If the batch reverts, and it contains more than a single call, then wrap the revert with ExecuteError,
60
+ * to mark the failing call index.
61
+ */
62
+ function executeBatch (Call[] calldata calls ) external {
63
+ _requireForExecute ();
64
+
65
+ for (uint256 i = 0 ; i < calls.length ; i++ ) {
66
+ Call calldata call = calls[i];
67
+ bool ok = Exec.call (call.target, call.value, call.data, gasleft ());
68
+ if (! ok) {
69
+ if (calls.length == 1 ) {
70
+ Exec.revertWithReturnData ();
71
+ } else {
72
+ revert ExecuteError (i, Exec.getReturnData (0 ));
73
+ }
74
+ }
75
+ }
76
+ }
77
+
34
78
/// @inheritdoc IAccount
35
79
function validateUserOp (
36
80
PackedUserOperation calldata userOp ,
@@ -53,6 +97,10 @@ abstract contract BaseAccount is IAccount {
53
97
);
54
98
}
55
99
100
+ function _requireForExecute () internal view virtual {
101
+ _requireFromEntryPoint ();
102
+ }
103
+
56
104
/**
57
105
* Validate the signature is valid for this message.
58
106
* @param userOp - Validate the userOp.signature field.
@@ -102,9 +150,9 @@ abstract contract BaseAccount is IAccount {
102
150
*/
103
151
function _payPrefund (uint256 missingAccountFunds ) internal virtual {
104
152
if (missingAccountFunds != 0 ) {
105
- (bool success , ) = payable (msg .sender ).call {
106
- value: missingAccountFunds
107
- }("" );
153
+ (bool success ,) = payable (msg .sender ).call {
154
+ value: missingAccountFunds
155
+ }("" );
108
156
(success);
109
157
//ignore failure (its EntryPoint's job to verify, not account.)
110
158
}
0 commit comments