2
2
3
3
pragma solidity ^ 0.8.20 ;
4
4
5
- import {IEntryPoint, PackedUserOperation} from "../../interfaces/draft-IERC4337.sol " ;
5
+ import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol " ;
6
6
import {Math} from "../../utils/math/Math.sol " ;
7
7
import {Packing} from "../../utils/Packing.sol " ;
8
8
@@ -24,9 +24,9 @@ library ERC4337Utils {
24
24
function parseValidationData (
25
25
uint256 validationData
26
26
) internal pure returns (address aggregator , uint48 validAfter , uint48 validUntil ) {
27
- validAfter = uint48 (bytes32 (validationData).extract_32_6 (0x00 ));
28
- validUntil = uint48 (bytes32 (validationData).extract_32_6 (0x06 ));
29
- aggregator = address (bytes32 (validationData).extract_32_20 (0x0c ));
27
+ validAfter = uint48 (bytes32 (validationData).extract_32_6 (0 ));
28
+ validUntil = uint48 (bytes32 (validationData).extract_32_6 (6 ));
29
+ aggregator = address (bytes32 (validationData).extract_32_20 (12 ));
30
30
if (validUntil == 0 ) validUntil = type (uint48 ).max;
31
31
}
32
32
@@ -59,7 +59,8 @@ library ERC4337Utils {
59
59
(address aggregator1 , uint48 validAfter1 , uint48 validUntil1 ) = parseValidationData (validationData1);
60
60
(address aggregator2 , uint48 validAfter2 , uint48 validUntil2 ) = parseValidationData (validationData2);
61
61
62
- bool success = aggregator1 == address (0 ) && aggregator2 == address (0 );
62
+ bool success = aggregator1 == address (uint160 (SIG_VALIDATION_SUCCESS)) &&
63
+ aggregator2 == address (uint160 (SIG_VALIDATION_SUCCESS));
63
64
uint48 validAfter = uint48 (Math.max (validAfter1, validAfter2));
64
65
uint48 validUntil = uint48 (Math.min (validUntil1, validUntil2));
65
66
return packValidationData (success, validAfter, validUntil);
@@ -71,12 +72,7 @@ library ERC4337Utils {
71
72
return (aggregator_, block .timestamp < validAfter || validUntil < block .timestamp );
72
73
}
73
74
74
- /// @dev Computes the hash of a user operation with the current entrypoint and chainid.
75
- function hash (PackedUserOperation calldata self ) internal view returns (bytes32 ) {
76
- return hash (self, address (this ), block .chainid );
77
- }
78
-
79
- /// @dev Sames as {hash}, but with a custom entrypoint and chainid.
75
+ /// @dev Computes the hash of a user operation for a given entrypoint and chainid.
80
76
function hash (
81
77
PackedUserOperation calldata self ,
82
78
address entrypoint ,
@@ -103,24 +99,34 @@ library ERC4337Utils {
103
99
return result;
104
100
}
105
101
102
+ /// @dev Returns `factory` from the {PackedUserOperation}, or address(0) if the initCode is empty or not properly formatted.
103
+ function factory (PackedUserOperation calldata self ) internal pure returns (address ) {
104
+ return self.initCode.length < 20 ? address (0 ) : address (bytes20 (self.initCode[0 :20 ]));
105
+ }
106
+
107
+ /// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted.
108
+ function factoryData (PackedUserOperation calldata self ) internal pure returns (bytes calldata ) {
109
+ return self.initCode.length < 20 ? _emptyCalldataBytes () : self.initCode[20 :];
110
+ }
111
+
106
112
/// @dev Returns `verificationGasLimit` from the {PackedUserOperation}.
107
113
function verificationGasLimit (PackedUserOperation calldata self ) internal pure returns (uint256 ) {
108
- return uint128 (self.accountGasLimits.extract_32_16 (0x00 ));
114
+ return uint128 (self.accountGasLimits.extract_32_16 (0 ));
109
115
}
110
116
111
117
/// @dev Returns `accountGasLimits` from the {PackedUserOperation}.
112
118
function callGasLimit (PackedUserOperation calldata self ) internal pure returns (uint256 ) {
113
- return uint128 (self.accountGasLimits.extract_32_16 (0x10 ));
119
+ return uint128 (self.accountGasLimits.extract_32_16 (16 ));
114
120
}
115
121
116
122
/// @dev Returns the first section of `gasFees` from the {PackedUserOperation}.
117
123
function maxPriorityFeePerGas (PackedUserOperation calldata self ) internal pure returns (uint256 ) {
118
- return uint128 (self.gasFees.extract_32_16 (0x00 ));
124
+ return uint128 (self.gasFees.extract_32_16 (0 ));
119
125
}
120
126
121
127
/// @dev Returns the second section of `gasFees` from the {PackedUserOperation}.
122
128
function maxFeePerGas (PackedUserOperation calldata self ) internal pure returns (uint256 ) {
123
- return uint128 (self.gasFees.extract_32_16 (0x10 ));
129
+ return uint128 (self.gasFees.extract_32_16 (16 ));
124
130
}
125
131
126
132
/// @dev Returns the total gas price for the {PackedUserOperation} (ie. `maxFeePerGas` or `maxPriorityFeePerGas + basefee`).
@@ -129,22 +135,35 @@ library ERC4337Utils {
129
135
// Following values are "per gas"
130
136
uint256 maxPriorityFee = maxPriorityFeePerGas (self);
131
137
uint256 maxFee = maxFeePerGas (self);
132
- return Math.ternary (maxFee == maxPriorityFee, maxFee, Math. min (maxFee, maxPriorityFee + block .basefee ) );
138
+ return Math.min (maxFee, maxPriorityFee + block .basefee );
133
139
}
134
140
}
135
141
136
142
/// @dev Returns the first section of `paymasterAndData` from the {PackedUserOperation}.
137
143
function paymaster (PackedUserOperation calldata self ) internal pure returns (address ) {
138
- return address (bytes20 (self.paymasterAndData[0 :20 ]));
144
+ return self.paymasterAndData. length < 52 ? address ( 0 ) : address (bytes20 (self.paymasterAndData[0 :20 ]));
139
145
}
140
146
141
147
/// @dev Returns the second section of `paymasterAndData` from the {PackedUserOperation}.
142
148
function paymasterVerificationGasLimit (PackedUserOperation calldata self ) internal pure returns (uint256 ) {
143
- return uint128 (bytes16 (self.paymasterAndData[20 :36 ]));
149
+ return self.paymasterAndData. length < 52 ? 0 : uint128 (bytes16 (self.paymasterAndData[20 :36 ]));
144
150
}
145
151
146
152
/// @dev Returns the third section of `paymasterAndData` from the {PackedUserOperation}.
147
153
function paymasterPostOpGasLimit (PackedUserOperation calldata self ) internal pure returns (uint256 ) {
148
- return uint128 (bytes16 (self.paymasterAndData[36 :52 ]));
154
+ return self.paymasterAndData.length < 52 ? 0 : uint128 (bytes16 (self.paymasterAndData[36 :52 ]));
155
+ }
156
+
157
+ /// @dev Returns the forth section of `paymasterAndData` from the {PackedUserOperation}.
158
+ function paymasterData (PackedUserOperation calldata self ) internal pure returns (bytes calldata ) {
159
+ return self.paymasterAndData.length < 52 ? _emptyCalldataBytes () : self.paymasterAndData[52 :];
160
+ }
161
+
162
+ // slither-disable-next-line write-after-write
163
+ function _emptyCalldataBytes () private pure returns (bytes calldata result ) {
164
+ assembly ("memory-safe" ) {
165
+ result.offset := 0
166
+ result.length := 0
167
+ }
149
168
}
150
169
}
0 commit comments