22
33pragma solidity ^ 0.8.20 ;
44
5- import {IEntryPoint, PackedUserOperation} from "../../interfaces/draft-IERC4337.sol " ;
5+ import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol " ;
66import {Math} from "../../utils/math/Math.sol " ;
77import {Packing} from "../../utils/Packing.sol " ;
88
@@ -24,9 +24,9 @@ library ERC4337Utils {
2424 function parseValidationData (
2525 uint256 validationData
2626 ) 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 ));
3030 if (validUntil == 0 ) validUntil = type (uint48 ).max;
3131 }
3232
@@ -59,7 +59,8 @@ library ERC4337Utils {
5959 (address aggregator1 , uint48 validAfter1 , uint48 validUntil1 ) = parseValidationData (validationData1);
6060 (address aggregator2 , uint48 validAfter2 , uint48 validUntil2 ) = parseValidationData (validationData2);
6161
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));
6364 uint48 validAfter = uint48 (Math.max (validAfter1, validAfter2));
6465 uint48 validUntil = uint48 (Math.min (validUntil1, validUntil2));
6566 return packValidationData (success, validAfter, validUntil);
@@ -71,12 +72,7 @@ library ERC4337Utils {
7172 return (aggregator_, block .timestamp < validAfter || validUntil < block .timestamp );
7273 }
7374
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.
8076 function hash (
8177 PackedUserOperation calldata self ,
8278 address entrypoint ,
@@ -103,24 +99,34 @@ library ERC4337Utils {
10399 return result;
104100 }
105101
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+
106112 /// @dev Returns `verificationGasLimit` from the {PackedUserOperation}.
107113 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 ));
109115 }
110116
111117 /// @dev Returns `accountGasLimits` from the {PackedUserOperation}.
112118 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 ));
114120 }
115121
116122 /// @dev Returns the first section of `gasFees` from the {PackedUserOperation}.
117123 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 ));
119125 }
120126
121127 /// @dev Returns the second section of `gasFees` from the {PackedUserOperation}.
122128 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 ));
124130 }
125131
126132 /// @dev Returns the total gas price for the {PackedUserOperation} (ie. `maxFeePerGas` or `maxPriorityFeePerGas + basefee`).
@@ -129,22 +135,35 @@ library ERC4337Utils {
129135 // Following values are "per gas"
130136 uint256 maxPriorityFee = maxPriorityFeePerGas (self);
131137 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 );
133139 }
134140 }
135141
136142 /// @dev Returns the first section of `paymasterAndData` from the {PackedUserOperation}.
137143 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 ]));
139145 }
140146
141147 /// @dev Returns the second section of `paymasterAndData` from the {PackedUserOperation}.
142148 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 ]));
144150 }
145151
146152 /// @dev Returns the third section of `paymasterAndData` from the {PackedUserOperation}.
147153 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+ }
149168 }
150169}
0 commit comments