Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update EntryPoint.sol: Optimized Gas #345

Closed
wants to merge 3 commits into from

Conversation

0xScratch
Copy link

1st change -> uint256 i = 0; to uint256 i; : Usually default values of all unsigned integers are 0, thus it's kind of a waste of gas when we initialize it with 0 itself

2nd change -> i++ to ++i : '++i' gonna be more helpful here and costs less gas, But it can mess up with code's logic if not used carefully. Although, I don't find any issues with it in this solidity file but do make a check related to this change

Use of unchecked is well appreciated, otherwise that would be my third change..

Thanks!

@shahafn
Copy link
Contributor

shahafn commented Sep 27, 2023

Did you run any gas checks to see that it's indeed saving gas?

@0xScratch
Copy link
Author

0xScratch commented Sep 27, 2023

Oh yeah it obviously saves gas.. I run some kind of tests earlier on remix, like creating some random function and checking whether this thing real works.. And yea that did
Just give me some time for opening up my laptop and build a demo contract for you.

And yea, it doesn't matters whatever contract it is, these changes works everywhere!

You might find this helpful -> https://gist.github.com/grGred/9bab8b9bad0cd42fc23d4e31e7347144#for-loops-improvement

@0xScratch
Copy link
Author

@shahafn Hope this makes us more sure about it

This one is without any changes, like what most contracts still nail at this..and some even don't use unchecked whenever there's really no need of using the 'checker' provided by version 0.8. But anyways..Look at the gas costs
Gas_for_1

Required changes made here, Results proves the show!
Gas_For_2

Sorry, But I was kind of a bit lazy to have a gas-check for real contract, and need up to setup the foundry thing for it...But yea I am pretty sure these changes, works for every contract. Thanks!

@drortirosh
Copy link
Contributor

You don't need to setup foundry for gas checks. just run yarn gas-calc, and it updates the gas calculations file (reports/gas-checker.txt) is several scenarios (single userop, bundle, diff between 1-2 userops, diff between 10-11 userops, big and small and paymaster overhead)

The CI also tests the gas report, so you can see the effect of code changes in the git history..

@0xScratch
Copy link
Author

Looks like @drortirosh need to really make me understand what's going on..like you said, I cloned the repository in my local machine, ran the command yarn install at first, and then yarn gas-calc..But it didn't worked and this error got displayed
gas-calc

@drortirosh
Copy link
Contributor

you should either have docker and docker-compose installed on your machine.
if you only have "docker", you can run geth with

docker run -ti --rm --name geth \
        -p 8545:8545 \
        ethereum/client-go:release-1.10 \
        --http \
        --http.addr "0.0.0.0" \
        --http.api personal,eth,net,web3,debug \
        --http.vhosts '*,localhost,host.docker.internal' \
        --http.corsdomain '*' \
        --rpc.allow-unprotected-txs \
        --allow-insecure-unlock \
        --dev 

if you don't have docker installed either, you can run geth locally on your machine, with the above parameters..

the "gas-calc" script will use docker-compose only if it doesn't find geth running locally on port 8545.

@0xScratch
Copy link
Author

@drortirosh did exactly what you said..installed docker desktop and ran the provided code after running geth
Got this:
gas-calc

Really don't know what's going on here, Can't you run the gas-checks?

@drortirosh
Copy link
Contributor

Did you manage to run other tests ?
sorry I can't help you here - none of us is using Windows...
can you try to build it on a unix machine ?

@0xScratch
Copy link
Author

Which other tests?
Tbh, I don't really know why we are running tests in this case, cuz the changes I made won't mess up any of the previous code unless there's a syntax error (which I don't seem to be present here)

Maybe you can use this pull request as a reference -> allo-protocol/allo-v2#288
and this might help -> https://gist.github.com/grGred/9bab8b9bad0cd42fc23d4e31e7347144#for-loops-improvement

@drortirosh
Copy link
Contributor

Which other tests?

You know, yarn && yarn test, just to make sure the project is properly installed on your machine.
I really don't have an idea why it doesn't work for you.

@0xScratch
Copy link
Author

But there's a catch, I guess you are thinking that I made changes in this repository after cloning it down in my PC, but that isn't the case. For making these changes, I really don't need any cloning part to do cuz I know they don't make any errors. Just forked down this repository and made changes online..That's it.
Thus, other files than this haven't been changed by me. You can be sure of that

@0xScratch
Copy link
Author

Moreover both yarn and yarn test seems to be running I guess..see this

$ yarn test
Downloading compiler 0.8.15
Generating typings for: 119 artifacts in dir: typechain for target: ethers-v5
Successfully generated 294 typings!
Compiled 115 Solidity files successfully
duplicate definition - constructor
duplicate definition - constructor
duplicate definition - addStake(uint32)
duplicate definition - balanceOf(address)
duplicate definition - unlockStake()
duplicate definition - withdrawStake(address)
duplicate definition - withdrawTo(address,uint256)

  test Create2Factory
    √ should deploy the factory (1234ms)
    √ should deploy to known address (48ms)
    √ should deploy to different address based on salt (45ms)
  DepositPaymaster
    deposit
      - should deposit and read balance
      - should fail to withdraw without unlock
      - should fail to withdraw within the same block
      - should succeed to withdraw after unlock
    #validatePaymasterUserOp
      - should fail if no token
      - should fail with wrong token
      - should reject if no deposit
      - should reject if deposit is not locked
      - succeed with valid deposit
    #handleOps
      - should pay with deposit (and revert user's call) if user can't pay with tokens
      - should pay with tokens if available
  EntryPoint
node version: HardhatNetwork/2.17.2/@nomicfoundation/ethereumjs-vm/7.0.2
    Stake Management
      √ should deposit for transfer into EntryPoint (59ms)
      without stake
        √ should fail to stake without value (44ms)
        √ should fail to stake without delay
        √ should fail to unlock
      with stake of 2 eth
        √ should report "staked" state
        √ should succeed to stake again (176ms)
        √ should fail to withdraw before unlock
        with unlocked stake
          √ should report as "not staked"
          √ should report unstake state
          √ should fail to withdraw before unlock timeout
          √ should fail to unlock again
          after unstake delay
            √ adding stake should reset "unlockStake" (64ms)
            √ should fail to unlock again
            √ should succeed to withdraw (157ms)
      with deposit
        √ should be able to withdraw (268ms)
    #simulateValidation
      √ should not use banned ops during simulateValidation (501ms)
    flickering account validation
      √ should prevent leakage of basefee (112ms)
      √ should limit revert reason length before emitting it (527ms)
      warm/cold storage detection in simulation vs execution
        √ should prevent detection through getAggregator() (68ms)
        √ should prevent detection through paymaster.code.length (180ms)
    2d nonces
      √ should fail nonce with new key and seq!=0 (44ms)
      with key=1, seq=1
        √ should get next nonce value by getNonce
        √ should allow to increment nonce of different key (54ms)
        √ should allow manual nonce increment (521ms)
        √ should fail with nonsequential seq (43ms)
    without paymaster (account pays in eth)
      #handleOps
        √ should revert on signature failure (61ms)
  == est gas= 2150015
rcpt.gasUsed= 174545 0x932bcc43cbd8dfa1756a906f2dc957181e2b71cc6c1ed1f8e6b95bfa981e7af9
        == actual gasUsed (from tx receipt)= 174545
        == calculated gasUsed (paid to beneficiary)= BigNumber { value: "122224" }
        == gasDiff 46717
        √ account should pay for tx (569ms)
  == offset before BigNumber { value: "0" }
  == est gas= 1296198
rcpt.gasUsed= 1152176 0x78277949f7fc65e013682310261a2f90aa9b864a2462c63b7ca6d3ce5c9d8a12
        == actual gasUsed (from tx receipt)= 1152176
        == calculated gasUsed (paid to beneficiary)= BigNumber { value: "1099395" }
        == gasDiff 46745
  == offset after BigNumber { value: "45" }
        √ account should pay for high gas usage tx (862ms)
  == offset before BigNumber { value: "45" }
  == est gas= 1305079
        √ account should not pay if too low gas limit was set (991ms)
        √ legacy mode (maxPriorityFee==maxFeePerGas) should not use "basefee" opcode (540ms)
  == est gas= 2109133
rcpt.gasUsed= 114141 0x5094dfc8b30c50087529c1886ed0eb1e1fd58390497a5d18d999c4aaedf27c3e
        == actual gasUsed (from tx receipt)= 114141
        == calculated gasUsed (paid to beneficiary)= BigNumber { value: "61808" }
        == gasDiff 46717
        √ if account has a deposit, it should use it to pay (682ms)
        √ should pay for reverted tx (76ms)
rcpt.gasUsed= 114117 0x998b5b1df1275f4b72bb80984dcedf18802d156106ce6f6cc8b198c9ad847468
        == actual gasUsed (from tx receipt)= 114117
        == calculated gasUsed (paid to beneficiary)= BigNumber { value: "61808" }
        == gasDiff 46717
        √ #handleOp (single) (179ms)
        √ should fail to call recursively into handleOps (184ms)
        √ should report failure on insufficient verificationGas after creation (96ms)
      create account
        √ should reject create if sender address is wrong (46ms)
        √ should reject create if account not funded (118ms)
        == actual gasUsed (from tx receipt)= 416079
        == calculated gasUsed (paid to beneficiary)= BigNumber { value: "364052" }
        == gasDiff 46663
        √ should succeed to create account after prefund (203ms)
        √ should reject if account already created (43ms)
      batch multiple requests
        √ should execute
        √ should pay for tx
      aggregation tests
        √ should fail to execute aggregated account without an aggregator
        √ should fail to execute aggregated account with wrong aggregator (70ms)
        √ should reject non-contract (address(1)) aggregator (71ms)
        √ should fail to execute aggregated account with wrong agg. signature
        √ should run with multiple aggregators (and non-aggregated-accounts) (291ms)
        execution ordering
          create account
            √ simulateValidation should return aggregator and its stake (184ms)
            √ should create account in handleOps (87ms)
      with paymaster (account with no eth)
        √ should fail with nonexistent paymaster (53ms)
        √ should fail if paymaster has no deposit (81ms)
        √ should not revert when paymaster reverts with custom error on postOp (1085ms)
        == actual gasUsed (from tx receipt)= 419423
        == calculated gasUsed (paid to beneficiary)= BigNumber { value: "365834" }
        == gasDiff 46717
        √ paymaster should pay for tx (1116ms)
        √ simulateValidation should return paymaster stake and delay (468ms)
      Validation time-range
        validateUserOp time-range
          √ should accept non-expired owner (52ms)
          √ should not reject expired owner (77ms)
        validatePaymasterUserOp with deadline
          √ should accept non-expired paymaster request (58ms)
          √ should not reject expired paymaster request (48ms)
          time-range overlap of paymaster and account should intersect
            √ should use lower "after" value of paymaster (58ms)
            √ should use lower "after" value of account (60ms)
            √ should use higher "until" value of paymaster (70ms)
            √ should use higher "until" value of account (62ms)
            √ handleOps should revert on expired paymaster request (59ms)
        handleOps should abort on time-range
          √ should revert on expired account (77ms)
          √ should revert on date owner (73ms)
    ERC-165
      √ should return true for IEntryPoint interface ID
      √ should return true for pure EntryPoint, IStakeManager and INonceManager interface IDs
      √ should return false for a wrong interface
  EntryPointSimulations
    Simulation Contract Sanity checks
      √ deposit on simulation must be >= real entrypoint
      √ deposit without value on simulation must be >= real entrypoint (123ms)
      √ eth transfer on simulation must be >= real entrypoint
      √ eth transfer (even without value) on simulation must be >= real entrypoint (129ms)
    #simulateValidation
      √ should fail if validateUserOp fails (39ms)
      √ should report signature failure without revert (56ms)
      √ should revert if wallet not deployed (and no initCode)
      √ should revert on oog if not enough verificationGas (57ms)
      √ should succeed if validateUserOp succeeds (86ms)
      √ should return empty context if no paymaster (41ms)
      √ should return stake of sender (600ms)
      √ should prevent overflows: fail if any numeric value is more than 120 bits
      √ should fail creation for wrong sender (50ms)
      √ should report failure on insufficient verificationGas (OOG) for creation (129ms)
      √ should succeed for creating an account (373ms)
      √ should not call initCode from entrypoint (456ms)
    #simulateHandleOp
      √ should simulate execution (509ms)
  Gnosis Proxy
    √ #getCurrentEIP4337Manager (57ms)
    √ should validate (48ms)
    √ should fail from wrong entrypoint (111ms)
    √ should fail on invalid userop (117ms)
gasUsed= BigNumber { value: "199875" } 0x08c0ff9c0d8d87cdfa382ceeeb1c1ecea42f9344c09658b2b6aca59833289755
    √ should exec (836ms)
gasUsed= BigNumber { value: "149311" } 0xb7dfa71dcef07eafbf15b0d34b4693f79dbcc71a8df5f03243d1c0806cb1695e
    √ should revert with reason (788ms)
gasUsed= BigNumber { value: "466955" } 0x664f8024545beb907275128f00624747b92da09151e17f19e146616549a13b0c
    √ should create account (1267ms)
gasUsed= BigNumber { value: "165699" } 0x0b5373ba0a2330766dd6f61f6e400956c7ae5cbd5dcee7a2c1640058ad9dc02f
    √ another op after creation (918ms)
    √ should validate ERC1271 signatures (80ms)
    #replaceEIP4337
      √ should reject to replace if wrong old manager
      √ should replace manager (1232ms)
  #ValidationData helpers
    √ #parseValidationData
    √ #packValidationData
    √ #packValidationData with aggregator
    √ #intersectTimeRange (46ms)
  EntryPoint with paymaster
node version: HardhatNetwork/2.17.2/@nomicfoundation/ethereumjs-vm/7.0.2
    #TokenPaymaster
      √ owner should have allowance to withdraw funds
      √ should allow only NEW owner to move funds after transferOwnership (136ms)
    using TokenPaymaster (account pays in paymaster tokens)
      #handleOps
        √ paymaster should reject if account doesn't have tokens (210ms)
      create account
        √ should reject if account not funded (93ms)
        == create gasUsed= 411815
        == actual gasUsed (from tx receipt)= 411815
        == calculated gasUsed (paid to beneficiary)= BigNumber { value: "359359" }
        == gasDiff 46724
        √ should succeed to create account with tokens (221ms)
        √ account should pay for its creation (in tst) (39ms)
        √ should reject if account already created
        √ batched request should each pay for its share (3675ms)
        grief attempt
          √ griefing attempt should cause handleOp to revert (411ms)
      withdraw
        √ should fail to withdraw before unstake
        √ should be able to withdraw after unstake delay (325ms)
  OracleHelper
    with one-hop direct price ETH per TOKEN
      √ should figure out the correct price (50ms)
    with one-hop reverse price TOKEN per ETH
      √ should figure out the correct price (57ms)
    with two-hops price USD-per-TOKEN and USD-per-ETH
      √ should figure out the correct price (56ms)
  TokenPaymaster
node version: HardhatNetwork/2.17.2/@nomicfoundation/ethereumjs-vm/7.0.2
    √ paymaster should reject if account does not have enough tokens or allowance (200ms)
    √ should be able to sponsor the UserOp while charging correct amount of ERC-20 tokens (206ms)
    √ should update cached token price if the change is above configured percentage (243ms)
    √ should use token price supplied by the client if it is better than cached (216ms)
    √ should use cached token price if the one supplied by the client if it is worse (206ms)
    √ should charge the overdraft tokens if the pre-charge ended up lower than the final transaction cost (348ms)
    √ should revert in the first postOp run if the pre-charge ended up lower than the final transaction cost but the client has no tokens to cover the overdraft (308ms)
    √ should swap tokens for ether if it falls below configured value and deposit it (519ms)
  SimpleAccount
    √ owner should be able to call transfer (442ms)
    √ other account should not be able to call transfer (351ms)
    √ should pack in js the same as solidity
    #executeBatch
      √ should allow zero value array (148ms)
      √ should allow transfer value (190ms)
      √ should fail with wrong array length
    #validateUserOp
      √ should pay
      √ should return NO_SIG_VALIDATION on wrong signature
    SimpleAccountFactory
      √ sanity: check deployer (402ms)
  EntryPoint with VerifyingPaymaster
    #parsePaymasterAndData
0x2625760c4a8e8101801d3a48ee64b2bea42f1e9600000000000000000000000000000000000000000000000000000000deadbeef00000000000000000000000000000000000000000000000000000000000012341234
      √ should parse data properly
    #validatePaymasterUserOp
      √ should reject on no signature (54ms)
      √ should reject on invalid signature (60ms)
      √ succeed with valid signature (79ms)
      with wrong signature
        √ should return signature error (no revert) on wrong signer signature (39ms)
        √ handleOp revert on signature failure in handleOps (54ms)
  bls account
    √ #getTrailingPublicKey
    √ #aggregateSignatures (85ms)
    √ #userOpToMessage (225ms)
    √ #validateUserOpSignature (874ms)
    √ aggregated sig validation must succeed if off-chain UserOp sig succeeds (1205ms)
verifyMultiple (mcl code) 13 ms
validateSignatures gas=  BigNumber { value: "352094" }
validateSignatures (on-chain) 6357 ms
    √ validateSignatures (6503ms)
    #EntryPoint.simulateValidation with aggregator
      √ validate after simulation returns ValidationResultWithAggregation (481ms)
  146 passing (55s)
  11 pending

@drortirosh
Copy link
Contributor

ok, great, so the yarn system works. I just can't understand why "yarn gas-calc" doesn't as it is built as just another "mocha test".

@0xScratch
Copy link
Author

hmm what next?

@drortirosh
Copy link
Contributor

I checked out your code, and ran the test.
this is the diff on the gas results:

║                                │       │               │    one UserOp) │     account.exec()) ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ simple                         │     1 │         81954 │                │                     ║
+║ simple                         │     1 │         81942 │                │                     ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ simple - diff from previous    │     2 │               │          44175 │               15185 ║
+║ simple - diff from previous    │     2 │               │          44223 │               15221 ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ simple                         │    10 │        480006 │                │                     ║
+║ simple                         │    10 │        479958 │                │                     ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ simple - diff from previous    │    11 │               │          44259 │               15269 ║
+║ simple - diff from previous    │    11 │               │          44271 │               15269 ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
 ║ simple paymaster               │     1 │         88237 │                │                     ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ simple paymaster with diff     │     2 │               │          43200 │               14210 ║
+║ simple paymaster with diff     │     2 │               │          43188 │               14186 ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ simple paymaster               │    10 │        477158 │                │                     ║
+║ simple paymaster               │    10 │        477230 │                │                     ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ simple paymaster with diff     │    11 │               │          43271 │               14281 ║
+║ simple paymaster with diff     │    11 │               │          43199 │               14197 ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
 ║ big tx 5k                      │     1 │        183011 │                │                     ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ big tx - diff from previous    │     2 │               │         144722 │               19462 ║
+║ big tx - diff from previous    │     2 │               │         144686 │               19426 ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ big tx 5k                      │    10 │       1485614 │                │                     ║
+║ big tx 5k                      │    10 │       1485638 │                │                     ║
 ╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
-║ big tx - diff from previous    │    11 │               │         144735 │               19475 ║
+║ big tx - diff from previous    │    11 │               │         144747 │               19487 ║
 ╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝
 

explanation:

  • your code saved 12 gas for a single-userop bundle

  • it saved 48 gas for a 10-userop bundle (or 4.8 gas per userop)
    both values are insignificant.

  • for a 10-userop bundle with paymaster (or with huge tx) there is a setback of 72 gas and 24 gas, both of which insignificant either.

bottom line: This is not an optimization at all. +/- 30 gas is observable on irrelevant minor changes such as adding/removing external functions (since they modify the "jump table")

Thank you for the effort.
I do suggest you investigate why you can't run the gas calculation on a windows machine (one option could be to run it inside a virtualized linux box..)

@0xScratch
Copy link
Author

will look at it!

Can make some more changes in two more files..Should I?
Still, if this doesn't make a big difference between gas costs, we can say this kind of a good practice. Moreover, have seen this practice often in this codebase, just not at some instances.

@drortirosh
Copy link
Contributor

you may suggest more optimization. but please find a way to run the gas checks too (e.g. by starting a docker or cloud image, or find how to make it run on Windows)

@0xScratch
Copy link
Author

Looks like I got something useful here!

$ yarn gas-calc
Using GETH on localhost:8545


  gas calculations
signer= 0x278ceA4058c2bBD0f60B8f6076B8B8E3F93F1478
bal= 115792089237316195423570985008687907853269984665640564039457.584007913129639927
DONT use geth miner.. use account 2 instead
node version: Geth/v1.10.26-stable-e5eb32ac/linux-amd64/go1.18.8
inittable
== running test count= 1
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 1802
count 1 gasUsed 106954
handleOps tx.hash= 0xbc089fded9a2a00c09ab9ae7767abb02839a8f82b535c73e317797f6d9f57b58
{ count: 1, gasUsed: 106954, accountEst: 29014, title: 'simple' }
    √ warmup (1274ms)

  simple account
== running test count= 1
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 1802
count 1 gasUsed 81954
handleOps tx.hash= 0x19f913f3f2a3ccabfd7508d09f1b21510d9165d3c7584130168004997ea54621
{ count: 1, gasUsed: 81954, accountEst: 29014, title: 'simple' }
== running test count= 2
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 3402
count 2 gasUsed 126141
        gas diff= 44187
handleOps tx.hash= 0xb18241e16354fbe0d4b38d40b5a8fada1d64afa2138b667c8a622a09dac3a4b1
{
  count: 2,
  gasUsed: 126141,
  accountEst: 29014,
  title: 'simple - diff from previous',
  gasDiff: 44187
}
    √ simple 1 (1007ms)
== running test count= 10
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 16202
count 10 gasUsed 479898
handleOps tx.hash= 0x3800ad44e4d3aeb1393a011c99cc04928c65d1269281c71080b797dd6e09e25f
{ count: 10, gasUsed: 479898, accountEst: 29014, title: 'simple' }
== running test count= 11
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 17802
count 11 gasUsed 524169
        gas diff= 44271
handleOps tx.hash= 0xcd159a55f40c7c961d7144471ce7975afe37555a1f87cb7f0e7908192264ed2c
{
  count: 11,
  gasUsed: 524169,
  accountEst: 29014,
  title: 'simple - diff from previous',
  gasDiff: 44271
}
    √ simple 10 (3238ms)

  Minimal Paymaster
== running test count= 1
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 1866
count 1 gasUsed 88237
handleOps tx.hash= 0x49d2cbdc2f75eb511857e38bcf3686a259de71e72a20dd0001e0f9b10c5ece4e
{
  count: 1,
  gasUsed: 88237,
  accountEst: 29014,
  title: 'simple paymaster'
}
== running test count= 2
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 3530
count 2 gasUsed 131437
        gas diff= 43200
handleOps tx.hash= 0x496a2ecbfeb5e0dc6ab3515986278870d33e4ab1c5d2bc5d256d09fd91b6755b
{
  count: 2,
  gasUsed: 131437,
  accountEst: 29014,
  title: 'simple paymaster with diff',
  gasDiff: 43200
}
    √ simple paymaster (687ms)
== running test count= 10
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 16842
count 10 gasUsed 477146
handleOps tx.hash= 0x891ff70df1f34b1f061a7c8b56787d1c69b8a7292facefc8113a7931db8dc260
{
  count: 10,
  gasUsed: 477146,
  accountEst: 29014,
  title: 'simple paymaster'
}
== running test count= 11
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 18506
count 11 gasUsed 520417
        gas diff= 43271
handleOps tx.hash= 0x95fd3b03048cd967818ff0a3bce0de57a06c3b6144ea67bbfeac7895acbd3c57
{
  count: 11,
  gasUsed: 520417,
  accountEst: 29014,
  title: 'simple paymaster with diff',
  gasDiff: 43271
}
    √ simple paymaster 10 (3245ms)

  huge tx - 5k
== running test count= 1
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 11978
count 1 gasUsed 182975
handleOps tx.hash= 0x9880e0aa8d2e81e998784f61ccbe3d6fa1fa5f29f481463bfe3ace5757f1f950
{ count: 1, gasUsed: 182975, accountEst: 125248, title: 'big tx 5k' }
== running test count= 2
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 23754
count 2 gasUsed 327685
        gas diff= 144710
handleOps tx.hash= 0x3e7bf244717c5d4c583740840d82d78258fe1c63b8235d502f616e6c95dcb572
{
  count: 2,
  gasUsed: 327685,
  accountEst: 125248,
  title: 'big tx - diff from previous',
  gasDiff: 144710
}
    √ big tx 5k (930ms)
== running test count= 10
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 117962
count 10 gasUsed 1485530
handleOps tx.hash= 0x4b0b313bd9f1e193225b647f60070cc2886e4e063070ded8ef7e08ee5e44b1cb
{ count: 10, gasUsed: 1485530, accountEst: 125248, title: 'big tx 5k' }
== running test count= 11
factaddr 0xdbf8416216edde27384ba12b04e29a1322369b89
=== encoded data= 129738
count 11 gasUsed 1630313
        gas diff= 144783
handleOps tx.hash= 0xe8702ab8aed393073b93a3b8a3230e5c73e2a064be6eab8f8cf775959da8a9ce
{
  count: 11,
  gasUsed: 1630313,
  accountEst: 125248,
  title: 'big tx - diff from previous',
  gasDiff: 144783
}
    √ big tx 10 (4174ms)

== gas estimate of direct calling the account's "execute" method
   the destination is "account.entryPoint()", which is known to be "hot" address used by this account
   it little higher than EOA call: its an exec from entrypoint (or account owner) into account contract, verifying msg.sender and exec to target)
╔══════════════════════════╤════════╗
║ gas estimate "simple"    │  29014 ║
╟──────────────────────────┼────────╢
║ gas estimate "big tx 5k" │ 125248 ║
╚══════════════════════════╧════════╝

╔════════════════════════════════╤═══════╤═══════════════╤════════════════╤═════════════════════╗
║ handleOps description          │ count │ total gasUsed │ per UserOp gas │ per UserOp overhead ║
║                                │       │               │     (delta for │        (compared to ║
║                                │       │               │    one UserOp) │     account.exec()) ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple                         │     1 │         81954 │                │                     ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple - diff from previous    │     2 │               │          44187 │               15173 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple                         │    10 │        479898 │                │                     ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple - diff from previous    │    11 │               │          44271 │               15257 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster               │     1 │         88237 │                │                     ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster with diff     │     2 │               │          43200 │               14186 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster               │    10 │        477146 │                │                     ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ simple paymaster with diff     │    11 │               │          43271 │               14257 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx 5k                      │     1 │        182975 │                │                     ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx - diff from previous    │     2 │               │         144710 │               19462 ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx 5k                      │    10 │       1485530 │                │                     ║
╟────────────────────────────────┼───────┼───────────────┼────────────────┼─────────────────────╢
║ big tx - diff from previous    │    11 │               │         144783 │               19535 ║
╚════════════════════════════════╧═══════╧═══════════════╧════════════════╧═════════════════════╝


  7 passing (15s)

@drortirosh
Copy link
Contributor

please don't copy the gas report text into the comment - add it as a commit

@0xScratch
Copy link
Author

Actually, that was just to show you. Moreover, it was just a test run for the original codebase, it doesn't include any of my changes.
So, Now I need to make my changes in the branch and run yarn gas-checks. And then update the gas reports, right?

@0xScratch
Copy link
Author

Made some changes in BLSSignatureAggregator.sol and got these results

account-abstraction

@drortirosh
Copy link
Contributor

So, Now I need to make my changes in the branch and run yarn gas-checks. And then update the gas reports, right?
Yes.
So how did you make gas-checks work on Windows? I want to document it for other users

@0xScratch
Copy link
Author

So how did you make gas-checks work on Windows? I want to document it for other users

You need three things for that, docker desktop installed, command prompt and git bash

  • First, run the command yarn install either in the terminal or bash...Sometimes it works in one and not in other, so try both.
  • then run the below command in a terminal, this will run a geth image inside the docker itself. (Try assigning this command in a straight line, else you will face some problems right inside the terminal)
    docker run -ti --rm --name geth \
          -p 8545:8545 \
          ethereum/client-go:release-1.10 \
          --http \
          --http.addr "0.0.0.0" \
          --http.api personal,eth,net,web3,debug \
          --http.vhosts '*,localhost,host.docker.internal' \
          --http.corsdomain '*' \
          --rpc.allow-unprotected-txs \
          --allow-insecure-unlock \
          --dev 
    
  • With the above command, geth will be running on your terminal. Now switch to git bash and run yarn test, just to check if everything works great.
  • Then we are good to go, run yarn gas-calc.
  • Also there's one more issue, I don't know much about it like why it is there and other things. Anyways, it doesn't let you run yarn gas-calc more than one or two times. like showing you errors (felt like it wanted me to use a different signer or account). But yea, for this just stop the geth blockchain and run it again..

@drortirosh
Copy link
Contributor

the overall I see from the commited gas results is that it causes slight increase in gas - insignificant (10s of gas on 10 userops) - but of course, there's no reason to include.
If you do find a way to reduce gas used by UserOp significantly (for both single and bundled calls), while still not breaking the usability and readability of the EntryPoint, then we would love to include it..

@0xScratch
Copy link
Author

Got it!

Just went through Entrypoint.sol, I noticed that you have used a function called innerHandleOp whose visibility is set to external, but it contains a require statement which is -> require(msg.sender == address(this), "AA92 internal call only");

Kind of wondering why is that, cuz this requirement statement stresses the visibility of this function as internal if I am not wrong here. If this is case then why don't we just remove that require statement and mark the visibility of this function as internal itself

@drortirosh
Copy link
Contributor

a function called innerHandleOp whose visibility is set to external

We have to open a separate context.
Execution contains calling callData and the paymaster.postOp.
Revert i
In postOp should also revert the callData that was executed just before it.

There is no way in solidity (or rather evm) to revert 2 method calls together, unless they are in an "external call"

@drortirosh
Copy link
Contributor

Re: docker

  1. Doesn't "yarn gas-calc" by itself run the docker for geth? It should detect it isn't running, and run the whole test using docker-compose
  2. Yes, you need to restart geth before the test. This gas-sensitive test requires a known state of geth to avoid had fluctuations

@0xScratch
Copy link
Author

  1. Doesn't "yarn gas-calc" by itself run the docker for geth? It should detect it isn't running, and run the whole test using docker-compose

Nope, in my case "yarn gas-calc" just checks whether the geth is running or not. If not, it doesn't try to run any docker for geth itself..just shows an error msg

@0xScratch
Copy link
Author

There is no way in solidity (or rather evm) to revert 2 method calls together, unless they are in an "external call"

Got it!

@drortirosh drortirosh closed this Dec 7, 2023
@0xScratch 0xScratch deleted the patch-1 branch December 7, 2023 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants