@@ -7,6 +7,7 @@ import "../interfaces/IAccount.sol";
77import "../interfaces/IAccountExecute.sol " ;
88import "../interfaces/IPaymaster.sol " ;
99import "../interfaces/IEntryPoint.sol " ;
10+ import "../interfaces/ISscOpcodes.sol " ;
1011
1112import "../utils/Exec.sol " ;
1213import "./StakeManager.sol " ;
@@ -28,8 +29,20 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
2829
2930 using UserOperationLib for PackedUserOperation;
3031
32+ int256 constant public SSC_STORAGE_SLOT_COST = 12800000000000000 ;
33+ int256 constant public SSC_STORAGE_SLOT_REFUND = 12672000000000000 ;
34+
35+ int256 constant public SSC_ACCOUNT_COST = 12800000000000000 ;
36+ int256 constant public SSC_ACCOUNT_REFUND = 12672000000000000 ;
37+
38+ int256 constant public SSC_CODE_CREATED_COST = 12800000000000000 ;
39+
40+ uint256 constant public SSC_MAX_SPEND_FACTOR = 10 ;
41+
3142 SenderCreator private immutable _senderCreator = new SenderCreator ();
3243
44+ ISscOpcodes private immutable _ssc = ISscOpcodes (address (0x665e930982A9a03c844641d453a2C3462ED7Ff41 ));
45+
3346 function senderCreator () internal view virtual returns (SenderCreator) {
3447 return _senderCreator;
3548 }
@@ -174,10 +187,12 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
174187 function handleOps (
175188 PackedUserOperation[] calldata ops ,
176189 address payable beneficiary
177- ) public nonReentrant {
190+ ) public nonReentrant payable {
178191 uint256 opslen = ops.length ;
179192 UserOpInfo[] memory opInfos = new UserOpInfo [](opslen);
180193
194+ int256 preSSC = _netSSC ();
195+
181196 unchecked {
182197 for (uint256 i = 0 ; i < opslen; i++ ) {
183198 UserOpInfo memory opInfo = opInfos[i];
@@ -200,7 +215,12 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
200215 collected += _executeUserOp (i, ops[i], opInfos[i]);
201216 }
202217
203- _compensate (beneficiary, collected);
218+ // this can be negative in cases of refunds
219+ int256 netSSC = _netSSC () - preSSC;
220+ // In case of negative netSSC msg.value must be higher than abs(netSSC)
221+ uint256 sscCompensation = uint256 (int256 (msg .value ) + netSSC);
222+
223+ _compensate (beneficiary, collected + sscCompensation);
204224 }
205225 }
206226
@@ -303,23 +323,10 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
303323 uint256 preOpGas;
304324 }
305325
306- /**
307- * Inner function to handle a UserOperation.
308- * Must be declared "external" to open a call context, but it can only be called by handleOps.
309- * @param callData - The callData to execute.
310- * @param opInfo - The UserOpInfo struct.
311- * @param context - The context bytes.
312- * @return actualGasCost - the actual cost in eth this UserOperation paid for gas
313- */
314- function innerHandleOp (
315- bytes memory callData ,
316- UserOpInfo memory opInfo ,
317- bytes calldata context
318- ) external returns (uint256 actualGasCost ) {
319- uint256 preGas = gasleft ();
326+ function innerExecuteCall (MemoryUserOp memory mUserOp , bytes memory callData ) external {
320327 require (msg .sender == address (this ), "AA92 internal call only " );
321- MemoryUserOp memory mUserOp = opInfo.mUserOp;
322328
329+ int256 preSSC = _netSSC ();
323330 uint256 callGasLimit = mUserOp.callGasLimit;
324331 unchecked {
325332 // handleOps was called with gas limit too low. abort entire bundle.
@@ -335,12 +342,46 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
335342 }
336343 }
337344 }
345+ if (callData.length > 0 ) {
346+ bool success = Exec.call (mUserOp.sender, 0 , callData, callGasLimit);
347+ if (! success) {
348+ require (false , string (Exec.getReturnData (REVERT_REASON_MAX_LEN)));
349+ } else {
350+ int256 netSSC = _netSSC () - preSSC;
351+ if (netSSC < 0 ) {
352+ // increment deposit for the user's account
353+ _incrementDeposit (mUserOp.sender, uint256 (- netSSC));
354+ } else {
355+ require (uint256 (netSSC) <= SSC_MAX_SPEND_FACTOR * callGasLimit * getUserOpGasPrice (mUserOp), "AA97 ssc max cost violation " );
356+ _decrementDeposit (mUserOp.sender, uint256 (netSSC));
357+ }
358+ }
359+ }
360+ }
361+
362+ /**
363+ * Inner function to handle a UserOperation.
364+ * Must be declared "external" to open a call context, but it can only be called by handleOps.
365+ * @param callData - The callData to execute.
366+ * @param opInfo - The UserOpInfo struct.
367+ * @param context - The context bytes.
368+ * @return actualGasCost - the actual cost in eth this UserOperation paid for gas
369+ */
370+ function innerHandleOp (
371+ bytes memory callData ,
372+ UserOpInfo memory opInfo ,
373+ bytes calldata context
374+ ) external returns (uint256 actualGasCost ) {
375+ uint256 preGas = gasleft ();
376+ require (msg .sender == address (this ), "AA92 internal call only " );
377+ MemoryUserOp memory mUserOp = opInfo.mUserOp;
338378
339379 IPaymaster.PostOpMode mode = IPaymaster.PostOpMode.opSucceeded;
340380 if (callData.length > 0 ) {
341- bool success = Exec.call (mUserOp.sender, 0 , callData, callGasLimit);
381+ (bool success , bytes memory result ) = address (this ).call (
382+ abi.encodeWithSelector (this .innerExecuteCall.selector , mUserOp, callData)
383+ );
342384 if (! success) {
343- bytes memory result = Exec.getReturnData (REVERT_REASON_MAX_LEN);
344385 if (result.length > 0 ) {
345386 emit UserOperationRevertReason (
346387 opInfo.userOpHash,
@@ -413,6 +454,15 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard,
413454 }
414455 }
415456
457+ /**
458+ * Calculates total ssc cost / refund
459+ */
460+ function _netSSC () internal view returns (int256 ) {
461+ return int256 (_ssc.accountsCreated ()) * SSC_ACCOUNT_COST - int256 (_ssc.accountsCleared ()) * SSC_ACCOUNT_REFUND
462+ + int256 (_ssc.slotsCreated ()) * SSC_STORAGE_SLOT_COST - int256 (_ssc.slotsCleared ()) * SSC_STORAGE_SLOT_REFUND
463+ + int256 (_ssc.codeCreated ()) * SSC_CODE_CREATED_COST;
464+ }
465+
416466 /**
417467 * Create sender smart contract account if init code is provided.
418468 * @param opIndex - The operation index.
0 commit comments