From 1a18ece5faf5204393ba643be4fc201d8b353bf6 Mon Sep 17 00:00:00 2001 From: Dror Tirosh Date: Sat, 6 Jan 2024 19:59:42 +0200 Subject: [PATCH 1/3] add postOp param (gasPrice) saves TokenPaymaster 731 gas (it currently required to pass maxFeePerGas and maxPriorityFee as context params) add "plain postOp" (which ignores this param) 24 gas. --- contracts/core/BasePaymaster.sol | 10 ++++--- contracts/core/EntryPoint.sol | 2 +- contracts/interfaces/IPaymaster.sol | 3 ++- contracts/samples/LegacyTokenPaymaster.sol | 4 +-- contracts/samples/TokenPaymaster.sol | 9 +++---- .../test/TestPaymasterRevertCustomError.sol | 2 +- contracts/test/TestPaymasterWithPostOp.sol | 3 ++- reports/gas-checker.txt | 26 +++++++++---------- 8 files changed, 30 insertions(+), 29 deletions(-) diff --git a/contracts/core/BasePaymaster.sol b/contracts/core/BasePaymaster.sol index dee42b2d..407e8832 100644 --- a/contracts/core/BasePaymaster.sol +++ b/contracts/core/BasePaymaster.sol @@ -54,10 +54,11 @@ abstract contract BasePaymaster is IPaymaster, Ownable { function postOp( PostOpMode mode, bytes calldata context, - uint256 actualGasCost + uint256 actualGasCost, + uint gasPrice ) external override { _requireFromEntryPoint(); - _postOp(mode, context, actualGasCost); + _postOp(mode, context, actualGasCost, gasPrice); } /** @@ -76,9 +77,10 @@ abstract contract BasePaymaster is IPaymaster, Ownable { function _postOp( PostOpMode mode, bytes calldata context, - uint256 actualGasCost + uint256 actualGasCost, + uint gasPrice ) internal virtual { - (mode, context, actualGasCost); // unused params + (mode, context, actualGasCost, gasPrice); // unused params // subclass must override this method if validatePaymasterUserOp returns a context revert("must override"); } diff --git a/contracts/core/EntryPoint.sol b/contracts/core/EntryPoint.sol index 0a6cc946..1d54d2d1 100644 --- a/contracts/core/EntryPoint.sol +++ b/contracts/core/EntryPoint.sol @@ -677,7 +677,7 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuard, if (mode != IPaymaster.PostOpMode.postOpReverted) { try IPaymaster(paymaster).postOp{ gas: mUserOp.verificationGasLimit - }(mode, context, actualGasCost) + }(mode, context, actualGasCost, gasPrice) // solhint-disable-next-line no-empty-blocks {} catch { bytes memory reason = Exec.getReturnData(REVERT_REASON_MAX_LEN); diff --git a/contracts/interfaces/IPaymaster.sol b/contracts/interfaces/IPaymaster.sol index 7a6e076e..520671b9 100644 --- a/contracts/interfaces/IPaymaster.sol +++ b/contracts/interfaces/IPaymaster.sol @@ -56,6 +56,7 @@ interface IPaymaster { function postOp( PostOpMode mode, bytes calldata context, - uint256 actualGasCost + uint256 actualGasCost, + uint gasPrice ) external; } diff --git a/contracts/samples/LegacyTokenPaymaster.sol b/contracts/samples/LegacyTokenPaymaster.sol index d9ebf9bc..f9129e48 100644 --- a/contracts/samples/LegacyTokenPaymaster.sol +++ b/contracts/samples/LegacyTokenPaymaster.sol @@ -102,11 +102,11 @@ contract LegacyTokenPaymaster is BasePaymaster, ERC20 { * the user's TX , back to the state it was before the transaction started (before the validatePaymasterUserOp), * and the transaction should succeed there. */ - function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) internal override { + function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint gasPrice) internal override { //we don't really care about the mode, we just pay the gas with the user's tokens. (mode); address sender = abi.decode(context, (address)); - uint256 charge = getTokenValueOfEth(actualGasCost + COST_OF_POST); + uint256 charge = getTokenValueOfEth(actualGasCost + COST_OF_POST * gasPrice); //actualGasCost is known to be no larger than the above requiredPreFund, so the transfer should succeed. _transfer(sender, address(this), charge); } diff --git a/contracts/samples/TokenPaymaster.sol b/contracts/samples/TokenPaymaster.sol index f5cfac58..1e7807a7 100644 --- a/contracts/samples/TokenPaymaster.sol +++ b/contracts/samples/TokenPaymaster.sol @@ -136,7 +136,7 @@ contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper { } uint256 tokenAmount = weiToToken(preChargeNative, cachedPriceWithMarkup); SafeERC20.safeTransferFrom(token, userOp.sender, address(this), tokenAmount); - context = abi.encode(tokenAmount, userOp.maxFeePerGas, userOp.maxPriorityFeePerGas, userOp.sender); + context = abi.encode(tokenAmount, userOp.sender); validationResult = _packValidationData( false, uint48(cachedPriceTimestamp + tokenPaymasterConfig.priceMaxAge), @@ -149,16 +149,13 @@ contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper { /// @dev This function is called after a user operation has been executed or reverted. /// @param context The context containing the token amount and user sender address. /// @param actualGasCost The actual gas cost of the transaction. - function _postOp(PostOpMode, bytes calldata context, uint256 actualGasCost) internal override { + function _postOp(PostOpMode, bytes calldata context, uint256 actualGasCost, uint gasPrice) internal override { unchecked { uint256 priceMarkup = tokenPaymasterConfig.priceMarkup; ( uint256 preCharge, - uint256 maxFeePerGas, - uint256 maxPriorityFeePerGas, address userOpSender - ) = abi.decode(context, (uint256, uint256, uint256, address)); - uint256 gasPrice = getGasPrice(maxFeePerGas, maxPriorityFeePerGas); + ) = abi.decode(context, (uint256, address)); uint256 _cachedPrice = updateCachedPrice(false); // note: as price is in ether-per-token and we want more tokens increasing it means dividing it by markup uint256 cachedPriceWithMarkup = _cachedPrice * PRICE_DENOMINATOR / priceMarkup; diff --git a/contracts/test/TestPaymasterRevertCustomError.sol b/contracts/test/TestPaymasterRevertCustomError.sol index b0be4b00..99b9acb2 100644 --- a/contracts/test/TestPaymasterRevertCustomError.sol +++ b/contracts/test/TestPaymasterRevertCustomError.sol @@ -33,7 +33,7 @@ contract TestPaymasterRevertCustomError is BasePaymaster { revertType = _revertType; } - function _postOp(PostOpMode, bytes calldata, uint256) internal view override { + function _postOp(PostOpMode, bytes calldata, uint256, uint256) internal view override { if (revertType == RevertType.customError){ revert CustomError("this is a long revert reason string we are looking for"); } diff --git a/contracts/test/TestPaymasterWithPostOp.sol b/contracts/test/TestPaymasterWithPostOp.sol index 694dde51..023d3056 100644 --- a/contracts/test/TestPaymasterWithPostOp.sol +++ b/contracts/test/TestPaymasterWithPostOp.sol @@ -24,7 +24,8 @@ contract TestPaymasterWithPostOp is TestPaymasterAcceptAll { function _postOp( PostOpMode mode, bytes calldata context, - uint256 actualGasCost + uint256 actualGasCost, + uint gasPrice ) internal override { } } diff --git a/reports/gas-checker.txt b/reports/gas-checker.txt index 3fbf000b..eb109910 100644 --- a/reports/gas-checker.txt +++ b/reports/gas-checker.txt @@ -14,17 +14,17 @@ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ simple │ 1 │ 81570 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple - diff from previous │ 2 │ │ 43842 │ 14863 ║ +║ simple - diff from previous │ 2 │ │ 43830 │ 14851 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple │ 10 │ 476227 │ │ ║ +║ simple │ 10 │ 476275 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ simple - diff from previous │ 11 │ │ 43873 │ 14894 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ simple paymaster │ 1 │ 87750 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster with diff │ 2 │ │ 42716 │ 13737 ║ +║ simple paymaster with diff │ 2 │ │ 42728 │ 13749 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster │ 10 │ 472423 │ │ ║ +║ simple paymaster │ 10 │ 472435 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ simple paymaster with diff │ 11 │ │ 42781 │ 13802 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ @@ -34,22 +34,22 @@ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ big tx 5k │ 10 │ 1481819 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ big tx - diff from previous │ 11 │ │ 144445 │ 19221 ║ +║ big tx - diff from previous │ 11 │ │ 144421 │ 19197 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp │ 1 │ 89483 │ │ ║ +║ paymaster+postOp │ 1 │ 89507 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp with diff │ 2 │ │ 44463 │ 15484 ║ +║ paymaster+postOp with diff │ 2 │ │ 44487 │ 15508 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp │ 10 │ 489783 │ │ ║ +║ paymaster+postOp │ 10 │ 490047 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp with diff │ 11 │ │ 44508 │ 15529 ║ +║ paymaster+postOp with diff │ 11 │ │ 44532 │ 15553 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ token paymaster │ 1 │ 147976 │ │ ║ +║ token paymaster │ 1 │ 147245 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ token paymaster with diff │ 2 │ │ 72659 │ 43680 ║ +║ token paymaster with diff │ 2 │ │ 71921 │ 42942 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ token paymaster │ 10 │ 802242 │ │ ║ +║ token paymaster │ 10 │ 794781 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ token paymaster with diff │ 11 │ │ 72727 │ 43748 ║ +║ token paymaster with diff │ 11 │ │ 71953 │ 42974 ║ ╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝ From 49e9917d56b0ca5fff4e7d310017172970f50abc Mon Sep 17 00:00:00 2001 From: Dror Tirosh Date: Mon, 8 Jan 2024 11:45:58 +0200 Subject: [PATCH 2/3] update erc --- erc/ERCS/erc-4337.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erc/ERCS/erc-4337.md b/erc/ERCS/erc-4337.md index 9d4a3f7e..3cf586e2 100644 --- a/erc/ERCS/erc-4337.md +++ b/erc/ERCS/erc-4337.md @@ -263,7 +263,7 @@ The paymaster interface is as follows: external returns (bytes memory context, uint256 validationData); function postOp - (PostOpMode mode, bytes calldata context, uint256 actualGasCost) + (PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint256 gasPrice) external; enum PostOpMode { From b7902f0bfaac69ecafe640c4ef9ed7e1afa8a656 Mon Sep 17 00:00:00 2001 From: Dror Tirosh Date: Mon, 8 Jan 2024 18:21:20 +0200 Subject: [PATCH 3/3] PR review rename field so we don't confuse userop-specific gasPrice with tx.gasprice --- contracts/core/BasePaymaster.sol | 13 ++++++---- contracts/interfaces/IPaymaster.sol | 5 +++- contracts/samples/LegacyTokenPaymaster.sol | 4 ++-- contracts/samples/TokenPaymaster.sol | 7 ++++-- contracts/test/TestPaymasterWithPostOp.sol | 11 +++------ erc/ERCS/erc-4337.md | 2 +- reports/gas-checker.txt | 28 +++++++++++----------- 7 files changed, 37 insertions(+), 33 deletions(-) diff --git a/contracts/core/BasePaymaster.sol b/contracts/core/BasePaymaster.sol index 407e8832..1089c191 100644 --- a/contracts/core/BasePaymaster.sol +++ b/contracts/core/BasePaymaster.sol @@ -55,10 +55,10 @@ abstract contract BasePaymaster is IPaymaster, Ownable { PostOpMode mode, bytes calldata context, uint256 actualGasCost, - uint gasPrice + uint actualUserOpFeePerGas ) external override { _requireFromEntryPoint(); - _postOp(mode, context, actualGasCost, gasPrice); + _postOp(mode, context, actualGasCost, actualUserOpFeePerGas); } /** @@ -72,15 +72,18 @@ abstract contract BasePaymaster is IPaymaster, Ownable { * postOpReverted - User op succeeded, but caused postOp (in mode=opSucceeded) to revert. * Now this is the 2nd call, after user's op was deliberately reverted. * @param context - The context value returned by validatePaymasterUserOp - * @param actualGasCost - Actual gas used so far (without this postOp call). + * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas + * and maxPriorityFee (and basefee) + * It is not the same as tx.gasprice, which is what the bundler pays. + */ function _postOp( PostOpMode mode, bytes calldata context, uint256 actualGasCost, - uint gasPrice + uint actualUserOpFeePerGas ) internal virtual { - (mode, context, actualGasCost, gasPrice); // unused params + (mode, context, actualGasCost, actualUserOpFeePerGas); // unused params // subclass must override this method if validatePaymasterUserOp returns a context revert("must override"); } diff --git a/contracts/interfaces/IPaymaster.sol b/contracts/interfaces/IPaymaster.sol index 520671b9..41f9b088 100644 --- a/contracts/interfaces/IPaymaster.sol +++ b/contracts/interfaces/IPaymaster.sol @@ -52,11 +52,14 @@ interface IPaymaster { * Now this is the 2nd call, after user's op was deliberately reverted. * @param context - The context value returned by validatePaymasterUserOp * @param actualGasCost - Actual gas used so far (without this postOp call). + * @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas + * and maxPriorityFee (and basefee) + * It is not the same as tx.gasprice, which is what the bundler pays. */ function postOp( PostOpMode mode, bytes calldata context, uint256 actualGasCost, - uint gasPrice + uint256 actualUserOpFeePerGas ) external; } diff --git a/contracts/samples/LegacyTokenPaymaster.sol b/contracts/samples/LegacyTokenPaymaster.sol index f9129e48..a8735f95 100644 --- a/contracts/samples/LegacyTokenPaymaster.sol +++ b/contracts/samples/LegacyTokenPaymaster.sol @@ -102,11 +102,11 @@ contract LegacyTokenPaymaster is BasePaymaster, ERC20 { * the user's TX , back to the state it was before the transaction started (before the validatePaymasterUserOp), * and the transaction should succeed there. */ - function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint gasPrice) internal override { + function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint actualUserOpFeePerGas) internal override { //we don't really care about the mode, we just pay the gas with the user's tokens. (mode); address sender = abi.decode(context, (address)); - uint256 charge = getTokenValueOfEth(actualGasCost + COST_OF_POST * gasPrice); + uint256 charge = getTokenValueOfEth(actualGasCost + COST_OF_POST * actualUserOpFeePerGas); //actualGasCost is known to be no larger than the above requiredPreFund, so the transfer should succeed. _transfer(sender, address(this), charge); } diff --git a/contracts/samples/TokenPaymaster.sol b/contracts/samples/TokenPaymaster.sol index 1e7807a7..7116e81d 100644 --- a/contracts/samples/TokenPaymaster.sol +++ b/contracts/samples/TokenPaymaster.sol @@ -149,7 +149,10 @@ contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper { /// @dev This function is called after a user operation has been executed or reverted. /// @param context The context containing the token amount and user sender address. /// @param actualGasCost The actual gas cost of the transaction. - function _postOp(PostOpMode, bytes calldata context, uint256 actualGasCost, uint gasPrice) internal override { + /// @param actualUserOpFeePerGas - the gas price this UserOp pays. This value is based on the UserOp's maxFeePerGas + // and maxPriorityFee (and basefee) + // It is not the same as tx.gasprice, which is what the bundler pays. + function _postOp(PostOpMode, bytes calldata context, uint256 actualGasCost, uint actualUserOpFeePerGas) internal override { unchecked { uint256 priceMarkup = tokenPaymasterConfig.priceMarkup; ( @@ -160,7 +163,7 @@ contract TokenPaymaster is BasePaymaster, UniswapHelper, OracleHelper { // note: as price is in ether-per-token and we want more tokens increasing it means dividing it by markup uint256 cachedPriceWithMarkup = _cachedPrice * PRICE_DENOMINATOR / priceMarkup; // Refund tokens based on actual gas cost - uint256 actualChargeNative = actualGasCost + tokenPaymasterConfig.refundPostopCost * gasPrice; + uint256 actualChargeNative = actualGasCost + tokenPaymasterConfig.refundPostopCost * actualUserOpFeePerGas; uint256 actualTokenNeeded = weiToToken(actualChargeNative, cachedPriceWithMarkup); if (preCharge > actualTokenNeeded) { // If the initially provided token amount is greater than the actual amount needed, refund the difference diff --git a/contracts/test/TestPaymasterWithPostOp.sol b/contracts/test/TestPaymasterWithPostOp.sol index 023d3056..9e793d85 100644 --- a/contracts/test/TestPaymasterWithPostOp.sol +++ b/contracts/test/TestPaymasterWithPostOp.sol @@ -13,19 +13,14 @@ contract TestPaymasterWithPostOp is TestPaymasterAcceptAll { constructor(IEntryPoint _entryPoint) TestPaymasterAcceptAll(_entryPoint) { } - function _validatePaymasterUserOp(UserOperation calldata userOp, bytes32 userOpHash, uint256 maxCost) + function _validatePaymasterUserOp(UserOperation calldata, bytes32, uint256) internal virtual override view returns (bytes memory context, uint256 validationData) { - (userOp, userOpHash, maxCost); // return a context, to force a call for postOp. return ("1", 0); } - function _postOp( - PostOpMode mode, - bytes calldata context, - uint256 actualGasCost, - uint gasPrice - ) internal override { + function _postOp(PostOpMode, bytes calldata, uint256, uint256) + internal override { } } diff --git a/erc/ERCS/erc-4337.md b/erc/ERCS/erc-4337.md index 3cf586e2..e765508f 100644 --- a/erc/ERCS/erc-4337.md +++ b/erc/ERCS/erc-4337.md @@ -263,7 +263,7 @@ The paymaster interface is as follows: external returns (bytes memory context, uint256 validationData); function postOp - (PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint256 gasPrice) + (PostOpMode mode, bytes calldata context, uint256 actualGasCost, uint256 actualUserOpFeePerGas) external; enum PostOpMode { diff --git a/reports/gas-checker.txt b/reports/gas-checker.txt index eb109910..8ceabd32 100644 --- a/reports/gas-checker.txt +++ b/reports/gas-checker.txt @@ -16,40 +16,40 @@ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ simple - diff from previous │ 2 │ │ 43830 │ 14851 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple │ 10 │ 476275 │ │ ║ +║ simple │ 10 │ 476239 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple - diff from previous │ 11 │ │ 43873 │ 14894 ║ +║ simple - diff from previous │ 11 │ │ 43885 │ 14906 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster │ 1 │ 87750 │ │ ║ +║ simple paymaster │ 1 │ 87738 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster with diff │ 2 │ │ 42728 │ 13749 ║ +║ simple paymaster with diff │ 2 │ │ 42716 │ 13737 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster │ 10 │ 472435 │ │ ║ +║ simple paymaster │ 10 │ 472351 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ simple paymaster with diff │ 11 │ │ 42781 │ 13802 ║ +║ simple paymaster with diff │ 11 │ │ 42709 │ 13730 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ big tx 5k │ 1 │ 182627 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ big tx - diff from previous │ 2 │ │ 144341 │ 19117 ║ +║ big tx - diff from previous │ 2 │ │ 144353 │ 19129 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ big tx 5k │ 10 │ 1481819 │ │ ║ +║ big tx 5k │ 10 │ 1481903 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ big tx - diff from previous │ 11 │ │ 144421 │ 19197 ║ +║ big tx - diff from previous │ 11 │ │ 144349 │ 19125 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ paymaster+postOp │ 1 │ 89507 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp with diff │ 2 │ │ 44487 │ 15508 ║ +║ paymaster+postOp with diff │ 2 │ │ 44475 │ 15496 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp │ 10 │ 490047 │ │ ║ +║ paymaster+postOp │ 10 │ 490011 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ paymaster+postOp with diff │ 11 │ │ 44532 │ 15553 ║ +║ paymaster+postOp with diff │ 11 │ │ 44544 │ 15565 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ token paymaster │ 1 │ 147245 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ ║ token paymaster with diff │ 2 │ │ 71921 │ 42942 ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ token paymaster │ 10 │ 794781 │ │ ║ +║ token paymaster │ 10 │ 794709 │ │ ║ ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢ -║ token paymaster with diff │ 11 │ │ 71953 │ 42974 ║ +║ token paymaster with diff │ 11 │ │ 72013 │ 43034 ║ ╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝