Skip to content

Commit fe4b2df

Browse files
authored
AA-467 Fixing actual gas used penalty (eth-infinitism#532)
* Passing actualGasCost with unused execution gas penalty to paymaster * Fixing verification gl overhead on simulations * Adding GasCalcPaymasterWithPostOp instead of the one used in tests
1 parent 61dc7ca commit fe4b2df

File tree

8 files changed

+300
-173
lines changed

8 files changed

+300
-173
lines changed

contracts/core/EntryPoint.sol

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -716,12 +716,20 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT
716716
uint256 gasPrice = getUserOpGasPrice(mUserOp);
717717

718718
address paymaster = mUserOp.paymaster;
719+
// Calculating a penalty for unused execution gas
720+
{
721+
uint256 executionGasUsed = actualGas - opInfo.preOpGas;
722+
// this check is required for the gas used within EntryPoint and not covered by explicit gas limits
723+
actualGas += _getUnusedGasPenalty(executionGasUsed, mUserOp.callGasLimit);
724+
}
725+
uint256 postOpUnusedGasPenalty;
719726
if (paymaster == address(0)) {
720727
refundAddress = mUserOp.sender;
721728
} else {
722729
refundAddress = paymaster;
723730
if (context.length > 0) {
724731
actualGasCost = actualGas * gasPrice;
732+
uint256 postOpPreGas = gasleft();
725733
if (mode != IPaymaster.PostOpMode.postOpReverted) {
726734
try IPaymaster(paymaster).postOp{
727735
gas: mUserOp.paymasterPostOpGasLimit
@@ -732,22 +740,12 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT
732740
revert PostOpReverted(reason);
733741
}
734742
}
743+
// Calculating a penalty for unused postOp gas
744+
uint256 postOpGasUsed = postOpPreGas - gasleft();
745+
postOpUnusedGasPenalty = _getUnusedGasPenalty(postOpGasUsed, mUserOp.paymasterPostOpGasLimit);
735746
}
736747
}
737-
actualGas += preGas - gasleft();
738-
739-
// Calculating a penalty for unused execution gas
740-
{
741-
uint256 executionGasLimit = mUserOp.callGasLimit + mUserOp.paymasterPostOpGasLimit;
742-
uint256 executionGasUsed = actualGas - opInfo.preOpGas;
743-
// this check is required for the gas used within EntryPoint and not covered by explicit gas limits
744-
if (executionGasLimit > executionGasUsed) {
745-
uint256 unusedGas = executionGasLimit - executionGasUsed;
746-
uint256 unusedGasPenalty = (unusedGas * PENALTY_PERCENT) / 100;
747-
actualGas += unusedGasPenalty;
748-
}
749-
}
750-
748+
actualGas += preGas - gasleft() + postOpUnusedGasPenalty;
751749
actualGasCost = actualGas * gasPrice;
752750
uint256 prefund = opInfo.prefund;
753751
if (prefund < actualGasCost) {
@@ -818,4 +816,15 @@ contract EntryPoint is IEntryPoint, StakeManager, NonceManager, ReentrancyGuardT
818816
(bool success, bytes memory ret) = target.delegatecall(data);
819817
revert DelegateAndRevert(success, ret);
820818
}
819+
820+
function _getUnusedGasPenalty(uint256 gasUsed, uint256 gasLimit) internal pure returns (uint256) {
821+
unchecked {
822+
if (gasLimit <= gasUsed) {
823+
return 0;
824+
}
825+
uint256 unusedGas = gasLimit - gasUsed;
826+
uint256 unusedGasPenalty = (unusedGas * PENALTY_PERCENT) / 100;
827+
return unusedGasPenalty;
828+
}
829+
}
821830
}

contracts/core/EntryPointSimulations.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ contract EntryPointSimulations is EntryPoint, IEntryPointSimulations {
192192

193193
//slightly stricter gas limit than the real EntryPoint
194194
function _getVerificationGasLimit(uint256 verificationGasLimit) internal pure virtual override returns (uint256) {
195-
return verificationGasLimit - 300;
195+
return verificationGasLimit - 500;
196196
}
197197

198198

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: GPL-3.0-only
2+
pragma solidity ^0.8.23;
3+
4+
import "./TestPaymasterAcceptAll.sol";
5+
/* solhint-disable no-empty-blocks */
6+
7+
/**
8+
* test paymaster, that pays for everything, without any check.
9+
* explicitly returns a context, to test cost (for entrypoint) to call postOp
10+
*/
11+
contract GasCalcPaymasterWithPostOp is TestPaymasterAcceptAll {
12+
constructor(IEntryPoint _entryPoint) TestPaymasterAcceptAll(_entryPoint) {
13+
}
14+
15+
function _validatePaymasterUserOp(PackedUserOperation calldata, bytes32, uint256)
16+
internal virtual override view
17+
returns (bytes memory context, uint256 validationData) {
18+
// return a context, to force a call for postOp.
19+
return ("1", SIG_VALIDATION_SUCCESS);
20+
}
21+
22+
function _postOp(PostOpMode, bytes calldata, uint256 actualGasCost, uint256)
23+
internal override {
24+
}
25+
}

contracts/test/TestPaymasterWithPostOp.sol

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import "./TestPaymasterAcceptAll.sol";
99
* explicitly returns a context, to test cost (for entrypoint) to call postOp
1010
*/
1111
contract TestPaymasterWithPostOp is TestPaymasterAcceptAll {
12+
event PostOpActualGasCost(uint256 actualGasCost);
1213

1314
constructor(IEntryPoint _entryPoint) TestPaymasterAcceptAll(_entryPoint) {
1415
}
@@ -20,7 +21,8 @@ contract TestPaymasterWithPostOp is TestPaymasterAcceptAll {
2021
return ("1", SIG_VALIDATION_SUCCESS);
2122
}
2223

23-
function _postOp(PostOpMode, bytes calldata, uint256, uint256)
24+
function _postOp(PostOpMode, bytes calldata, uint256 actualGasCost, uint256)
2425
internal override {
26+
emit PostOpActualGasCost(actualGasCost);
2527
}
2628
}

gascalc/4-paymaster-postop.gas.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { parseEther } from 'ethers/lib/utils'
2-
import { TestPaymasterWithPostOp__factory } from '../typechain'
2+
import { GasCalcPaymasterWithPostOp__factory } from '../typechain'
33
import { ethers } from 'hardhat'
44
import { GasChecker } from './GasChecker'
55
import { Create2Factory } from '../src/Create2Factory'
@@ -14,9 +14,9 @@ context('Paymaster with PostOp', function () {
1414
let paymasterAddress: string
1515

1616
before(async () => {
17-
const paymasterInit = hexValue(new TestPaymasterWithPostOp__factory(ethersSigner).getDeployTransaction(g.entryPoint().address).data!)
17+
const paymasterInit = hexValue(new GasCalcPaymasterWithPostOp__factory(ethersSigner).getDeployTransaction(g.entryPoint().address).data!)
1818
paymasterAddress = await new Create2Factory(ethers.provider, ethersSigner).deploy(paymasterInit, 0)
19-
const paymaster = TestPaymasterWithPostOp__factory.connect(paymasterAddress, ethersSigner)
19+
const paymaster = GasCalcPaymasterWithPostOp__factory.connect(paymasterAddress, ethersSigner)
2020
await paymaster.addStake(1, { value: 1 })
2121
await g.entryPoint().depositTo(paymaster.address, { value: parseEther('10') })
2222
})

reports/gas-checker.txt

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,36 @@
1212
║ │ │ │ (delta for │ (compared to ║
1313
║ │ │ │ one UserOp) │ account.exec()) ║
1414
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
15-
║ simple │ 1 │ 77450 │ │ ║
15+
║ simple │ 1 │ 77434 │ │ ║
1616
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
17-
║ simple - diff from previous │ 2 │ │ 4157412315
17+
║ simple - diff from previous │ 2 │ │ 4158212323
1818
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
19-
║ simple │ 10 │ 451932 │ │ ║
19+
║ simple │ 10 │ 451844 │ │ ║
2020
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
21-
║ simple - diff from previous │ 11 │ │ 4165912400
21+
║ simple - diff from previous │ 11 │ │ 4166712408
2222
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
23-
║ simple paymaster │ 1 │ 83281 │ │ ║
23+
║ simple paymaster │ 1 │ 83249 │ │ ║
2424
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
25-
║ simple paymaster with diff │ 2 │ │ 4010610847
25+
║ simple paymaster with diff │ 2 │ │ 4013410875
2626
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
27-
║ simple paymaster │ 10 │ 444654 │ │ ║
27+
║ simple paymaster │ 10 │ 444514 │ │ ║
2828
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
29-
║ simple paymaster with diff │ 11 │ │ 4019910940
29+
║ simple paymaster with diff │ 11 │ │ 4022710968
3030
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
31-
║ big tx 5k │ 1 │ 167209 │ │ ║
31+
║ big tx 5k │ 1 │ 167193 │ │ ║
3232
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
33-
║ big tx - diff from previous │ 2 │ │ 13081116109
33+
║ big tx - diff from previous │ 2 │ │ 13079516093
3434
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
35-
║ big tx 5k │ 10 │ 1344642 │ │ ║
35+
║ big tx 5k │ 10 │ 1344470 │ │ ║
3636
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
37-
║ big tx - diff from previous │ 11 │ │ 13078816086
37+
║ big tx - diff from previous │ 11 │ │ 13082016118
3838
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
39-
║ paymaster+postOp │ 1 │ 84458 │ │ ║
39+
║ paymaster+postOp │ 1 │ 84616 │ │ ║
4040
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
41-
║ paymaster+postOp with diff │ 2 │ │ 4131812059
41+
║ paymaster+postOp with diff │ 2 │ │ 4145212193
4242
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
43-
║ paymaster+postOp │ 10 │ 456453 │ │ ║
43+
║ paymaster+postOp │ 10 │ 457985 │ │ ║
4444
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
45-
║ paymaster+postOp with diff │ 11 │ │ 4136912110
45+
║ paymaster+postOp with diff │ 11 │ │ 4155112292
4646
╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝
4747

0 commit comments

Comments
 (0)