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

The gasUsed of each EVM call is not clear. #28074

Closed
xuht724 opened this issue Sep 7, 2023 · 20 comments
Closed

The gasUsed of each EVM call is not clear. #28074

xuht724 opened this issue Sep 7, 2023 · 20 comments

Comments

@xuht724
Copy link

xuht724 commented Sep 7, 2023

I am analysing the gas used distribution in a transaction. Here is a trace example and my analysis result. I am curious about why the calculated remaining gas is larger than the gas after the final call. (40554 > 36662)
Does any gas refund that I do not consider. How can I correctly get the gas used in each evm call.

Trx Hash 0xb06aca08b58e7b89c47aa33fd250560d3f2d8790902af2895d677c07111f40ca
trx gas 135181 trx used 94627
Transaction remaining gas 40554
accessList gas cost 33800
calldata_gascost 432
begin gas 79949

EVM Call Gas Distribution 
0x6b75d8af000000e20b7a7ddf000ba900b4009a80 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 transferFrom
Begin gas 78436 Call gas cost 8732 After Call Gas 69704
0x6b75d8af000000e20b7a7ddf000ba900b4009a80 0x3a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d v2swap
Begin gas 69682 Call gas cost 33020 After Call Gas 36662

{
    "from": "0xae2fc483527b8ef99eb5d9b44875f005ba1fae13",
    "gas": "0x1384d",
    "gasUsed": "0x171a3",
    "to": "0x6b75d8af000000e20b7a7ddf000ba900b4009a80",
    "input": "0x802f183a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d480d4c32",
    "calls": [
        {
            "from": "0x6b75d8af000000e20b7a7ddf000ba900b4009a80",
            "gas": "0x13264",
            "gasUsed": "0x221c",
            "to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
            "input": "0x23b872dd0000000000000000000000006b75d8af000000e20b7a7ddf000ba900b4009a800000000000000000000000003a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d0000000000000000000000000000000000000000000000000ab200a500000000",
            "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
            "value": "0x0",
            "type": "CALL"
        },
        {
            "from": "0x6b75d8af000000e20b7a7ddf000ba900b4009a80",
            "gas": "0x11032",
            "gasUsed": "0x80fc",
            "to": "0x3a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d",
            "input": "0x022c0d9f0000000000000000000000000000000000000000480d4c32000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006b75d8af000000e20b7a7ddf000ba900b4009a8000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000",
            "calls": [
                {
                    "from": "0x3a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d",
                    "gas": "0xf933",
                    "gasUsed": "0x28d0",
                    "to": "0x27f103f86070cc639fef262787a16887d22d8415",
                    "input": "0xa9059cbb0000000000000000000000006b75d8af000000e20b7a7ddf000ba900b4009a800000000000000000000000000000000000000000480d4c320000000000000000",
                    "output": "0x0000000000000000000000000000000000000000000000000000000000000001",
                    "value": "0x0",
                    "type": "CALL"
                },
                {
                    "from": "0x3a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d",
                    "gas": "0xce99",
                    "gasUsed": "0x2cb",
                    "to": "0x27f103f86070cc639fef262787a16887d22d8415",
                    "input": "0x70a082310000000000000000000000003a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d",
                    "output": "0x000000000000000000000000000000000000000b38821d736fa08423600f081b",
                    "type": "STATICCALL"
                },
                {
                    "from": "0x3a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d",
                    "gas": "0xca44",
                    "gasUsed": "0x216",
                    "to": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
                    "input": "0x70a082310000000000000000000000003a22710dbd18ddcfe64e28ed5a97fa4774fd2c3d",
                    "output": "0x000000000000000000000000000000000000000000000001b3cefd15d747e50e",
                    "type": "STATICCALL"
                }
            ],
            "value": "0x0",
            "type": "CALL"
        }
    ],
    "value": "0xab200a5",
    "type": "CALL"
}
@s1na
Copy link
Contributor

s1na commented Sep 8, 2023

The trace you posted doesn't seem to match the transaction hash. The input is different on etherscan.

But it's strange that the gasUsed is higher than gas on the top call of the trace you posted. Can you please find the right hash so we can investigate?
The only explanation would be if there was a lot of refunds. Or indicates a bug in the tracer.

@xuht724
Copy link
Author

xuht724 commented Sep 8, 2023

The trace you posted doesn't seem to match the transaction hash. The input is different on etherscan.

But it's strange that the gasUsed is higher than gas on the top call of the trace you posted. Can you please find the right hash so we can investigate? The only explanation would be if there was a lot of refunds. Or indicates a bug in the tracer.

Thank you for your correction. I have edited the comment and post the correct transaction trace. I have found many transactions like this. And I really curious about the reason.

@s1na
Copy link
Contributor

s1na commented Sep 8, 2023

Strangely enough what's wrong is the gasLimit, not gasUsed. What's reported in the trace doesn't match tx's gas limit. But this doesn't seem to be happening for all the txes. Trying to figure out in which case this happens.

@s1na
Copy link
Contributor

s1na commented Sep 8, 2023

Can you please find a recent tx (last 128 blocks ideally) for me to reproduce locally? Also which version are you running on?

@xuht724
Copy link
Author

xuht724 commented Sep 8, 2023

Strangely enough what's wrong is the gasLimit, not gasUsed. What's reported in the trace doesn't match tx's gas limit. But this doesn't seem to be happening for all the txes. Trying to figure out in which case this happens.

I could explain the difference between transaction gaslimit and trace limit. The trace limit is calculated by the transaction gas limit minus accessList gascost, calldata gascost and 21000 (transaction base cost).

@xuht724
Copy link
Author

xuht724 commented Sep 8, 2023

Can you please find a recent tx (last 128 blocks ideally) for me to reproduce locally? Also which version are you running on?

I think you can try the transaction hash:
0x3200bdf43b3f7290181da46b9996e09c2135625dd3d9358adc0e2b5aa5029e07
I am using Alchemy node service.
I speculate this is caused by the gas refund. But I do not know any method to get gas refund number of the transaction. Do you know any method to do?

@s1na
Copy link
Contributor

s1na commented Sep 8, 2023

> debug.traceTransaction('0x3200bdf43b3f7290181da46b9996e09c2135625dd3d9358adc0e2b5aa5029e07', { tracer: 'callTracer' }).gas
"0x318ee"
> eth.getTransaction('0x3200bdf43b3f7290181da46b9996e09c2135625dd3d9358adc0e2b5aa5029e07').gas
202990
> 0x318ee
202990

The gas limit issue was fixed 5 months ago #27029. I think Alchemy hasn't updated their nodes. But you said there's something else?

@xuht724
Copy link
Author

xuht724 commented Sep 8, 2023

> debug.traceTransaction('0x3200bdf43b3f7290181da46b9996e09c2135625dd3d9358adc0e2b5aa5029e07', { tracer: 'callTracer' }).gas
"0x318ee"
> eth.getTransaction('0x3200bdf43b3f7290181da46b9996e09c2135625dd3d9358adc0e2b5aa5029e07').gas
202990
> 0x318ee
202990

The gas limit issue was fixed 5 months ago #27029. I think Alchemy hasn't updated their nodes. But you said there's something else?

Thanks for your introduction. But my question focus on the gas refund. I notice that transaction remaining gas is higher than the last call remaining gas.
For transaction 0x3200bdf43b3f7290181da46b9996e09c2135625dd3d9358adc0e2b5aa5029e07
transaction remaining gas = 202990 - 142093 = 60897
Last Call remaining gas = 76550 - 22433 = 54117
I would like to ask the reason, may be it is caused by gas refund. But I do not know how to check it and how to calculate the gas refund.

@s1na
Copy link
Contributor

s1na commented Sep 8, 2023

According to this https://etherscan.io/vmtrace?txhash=0x3200bdf43b3f7290181da46b9996e09c2135625dd3d9358adc0e2b5aa5029e07&type=parity that's not the last call. The last call has 62635 gas and usage of 534 which turns out to be 62101 remaining gas.

@xuht724
Copy link
Author

xuht724 commented Sep 8, 2023

According to this https://etherscan.io/vmtrace?txhash=0x3200bdf43b3f7290181da46b9996e09c2135625dd3d9358adc0e2b5aa5029e07&type=parity that's not the last call. The last call has 62635 gas and usage of 534 which turns out to be 62101 remaining gas.

Yes. But please notice the action[9]. The gas is 76550 and gasused is 22433. You mentioned is the last subcall. I used the last topcall to calculate. Is there any mistake?
Besides, I want to ask if the gasUsed in the calltrace includes its subcall gasUsed. I think it should include but I want to check.

@s1na
Copy link
Contributor

s1na commented Sep 8, 2023

Yes. But please notice the action[9]. The gas is 76550 and gasused is 22433. You mentioned is the last subcall. I used the last topcall to calculate. Is there any mistake?

Ah of course you're right, my bad.

To see the refund you can do debug.traceTransaction('txhash'). The result is massive, it reports every opcode execution. But it does give a running total of refund gas at each point.

Besides, I want to ask if the gasUsed in the calltrace includes its subcall gasUsed. I think it should include but I want to check.

Yes it includes.

@xuht724
Copy link
Author

xuht724 commented Sep 8, 2023

Yes. But please notice the action[9]. The gas is 76550 and gasused is 22433. You mentioned is the last subcall. I used the last topcall to calculate. Is there any mistake?

Ah of course you're right, my bad.

To see the refund you can do debug.traceTransaction('txhash'). The result is massive, it reports every opcode execution. But it does give a running total of refund gas at each point.

Besides, I want to ask if the gasUsed in the calltrace includes its subcall gasUsed. I think it should include but I want to check.

Yes it includes.

Oh! Thanks. And I want ask if there is any rpc to get the debug.traceTransaction('txhash') result for gasrefund. Again, I want to ask if I want to simulate the trx locally, Can I get the trace information about gasrefund and how.

@s1na
Copy link
Contributor

s1na commented Sep 8, 2023

Oh! Thanks. And I want ask if there is any rpc to get the debug.traceTransaction('txhash') result for gasrefund. Again, I want to ask if I want to simulate the trx locally, Can I get the trace information about gasrefund and how.

Yes there's an RPC method with the same name. debug_traceTransaction. I think Alchemy only supports the callTracer and prestateTracer. So you will probably need a local synced node for this. But then you can see refunds with the default (opcode) tracer. Unfortunately my node doesn't have the state for the tx you sent anymore to check the refund myself.

@xuht724
Copy link
Author

xuht724 commented Sep 8, 2023

Really thanks for your help. And I want to if you know some ways to get trace for those transactions that I want to send (I want to check the gas_refund) using any framework. I am using hardhat for testing, but it seems its 'debug_transaction' rpc method will not return gasrefund result.

@jsvisa
Copy link
Contributor

jsvisa commented Sep 12, 2023

AFAIK, the opcode tracer will return the results by each op, I don't think there's any way yet to extract the callTracer's refund gas. Maybe we can make this happen after #27629 got merged

@fjl
Copy link
Contributor

fjl commented Sep 12, 2023

supertracer FTW

@s1na
Copy link
Contributor

s1na commented Sep 12, 2023

AFAIK, the opcode tracer will return the results by each op, I don't think there's any way yet to extract the callTracer's refund gas.

It does give you the current stand of the refund counter at each opcode. It should be enough to get an idea. Here is the refund value for the last opcodes in the trace. The last stand was 22700. But that doesn't mean all of it will be necessarily refunded. The refunds are capped to gasUsed / 5 = 28418 which in this case is bigger than the refund value. So the remaining gas of the tx must have been 38197 which is lower than the last call's remaining gas.

  }, {                                                                                                                                                 │········
      depth: 1,                                                                                                                                        │········
      gas: 88359,                                                                                                                                      │········
      gasCost: 8,                                                                                                                                      │········
      op: "JUMP",                                                                                                                                      │········
      pc: 7574,                                                                                                                                        │········
      refund: 22700,                                                                                                                                   │········
      stack: ["0xb6f9de95", "0x1d3"]                                                                                                                   │········
  }, {                                                                                                                                                 │········
      depth: 1,                                                                                                                                        │········
      gas: 88351,                                                                                                                                      │········
      gasCost: 1,                                                                                                                                      │········
      op: "JUMPDEST",                                                                                                                                  │········
      pc: 467,                                                                                                                                         │········
      refund: 22700,                                                                                                                                   │········
      stack: ["0xb6f9de95"]                                                                                                                            │········
  }, {                                                                                                                                                 │········
      depth: 1,                                                                                                                                        │········
      gas: 88350,                                                                                                                                      │········
      gasCost: 0,                                                                                                                                      │········
      op: "STOP",                                                                                                                                      │········
      pc: 468,                                                                                                                                         │········
      refund: 22700,                                                                                                                                   │········
      stack: ["0xb6f9de95"]                                                                                                                            │········
  }]

And I want to if you know some ways to get trace for those transactions that I want to send (I want to check the gas_refund) using any framework. I am using hardhat for testing, but it seems its 'debug_transaction' rpc method will not return gasrefund result.

Yes you will need a geth node. I can't help with hardhat unfortunately.

@s1na
Copy link
Contributor

s1na commented Sep 12, 2023

Closing the issue. Please re-open if you think the remaining gas value is incorrect.

@s1na s1na closed this as completed Sep 12, 2023
@xuht724
Copy link
Author

xuht724 commented Sep 12, 2023

supertracer FTW

Sorry I want to ask what is supertracer, I do not find any information about it.

@fjl
Copy link
Contributor

fjl commented Sep 14, 2023

Sorry, it was a joke comment. There is a proposed change to go-ethereum, #27629, that would make it possible to create traces during processing of blocks. It could help with your problem if we had that change in, that's why I wrote the comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants