go-ethereum
go-ethereum copied to clipboard
Native callTracer: missing CREATE2 frames where out of gas occur
System information
Geth version: 1.10.22-unstable
OS & Version: Ubuntu 20.04 LTS, 5.4.0-121-generic
Commit hash : 9d76a9b94f1d4f8b8a9c212151d96d6a13cb6ead
I am trying to migrate our datasource from openethereum to geth. For obtaining the same data, we want to use the tracer API of geth. When comparing data that we got from openethereum with geth, I can observe a very small discrepancy.
Expected behaviour
In instances where CREATE2 frames error out because the execution went out of gas, this seems not to be accurately depicted by geth. According to geth, the frame in which the "out of gas" occurs is the top level call frame, rather than the CREATE2 frame (which is missing in the result entirely).
Using the example below, I would expect the result to look similar to this:
{
"result": {
"type": "CALL",
"from": "0xb59bff945a74a427c74fb27ae423fcf81da27c24",
"to": "0xffa397285ce46fb78c588a9e993286aac68c37cd",
"value": "0x0",
"gas": "0x267a6",
"gasUsed": "0x267a6",
"input": "0xfb90b320000000000000000000000000c9b0576f11635e88cc040ebf13ef57f326f553110000000000000000000000000000000000000000000000000000000000000183",
"error": "out of gas",
"calls":[{
"type": "CREATE2",
"from": "0xffa397285ce46fb78c588a9e993286aac68c37cd",
"value": "0x0",
"input": "0x3d602d80600a3d3981f3363d3d373d3d3d363d73059ffafdc6ef594230de44f824e2bd0a51ca5ded5af43d82803e903d91602b57fd5bf3",
"gas": "0x1d8a7",
"gasUsed": "0x1d8a7",
"error": "out of gas"
}]
}
}
Actual behaviour
In the block range from 14992579 to 14999613 I was able to find seven such instances, all of them involving CREATE2 and out of gas:
| block | tx |
|---|---|
| 14992579 | 70 |
| 14993975 | 100 |
| 14993997 | 90 |
| 14997259 | 62 |
| 14997534 | 128 |
| 14999176 | 209 |
| 14999613 | 271 |
Steps to reproduce the behaviour
nc -U geth.ipc- example with the first entry in the table above:
{"jsonrpc": "2.0", "id": 1, "method": "debug_subscribe", "params": ["traceChain", "0xe4c4c2", "0xe4c4c3", {"tracer": "callTracer", "reexec": 2500000}]} - the full result can be viewed here, but the relevant part can be navigated to like this:
res['params']['result']['traces'][70], which in this case gives:
{
"result": {
"type": "CALL",
"from": "0xb59bff945a74a427c74fb27ae423fcf81da27c24",
"to": "0xffa397285ce46fb78c588a9e993286aac68c37cd",
"value": "0x0",
"gas": "0x267a6",
"gasUsed": "0x267a6",
"input": "0xfb90b320000000000000000000000000c9b0576f11635e88cc040ebf13ef57f326f553110000000000000000000000000000000000000000000000000000000000000183",
"error": "out of gas"
}
}
Let me know if there's anything else I can do to help recreate this problem.
Interesting. Just to make things clear, there are several things which could be going on here, so let's first define them.
- The
CREATE2call goes OOG. TheCREATE2opcode costs32000gas up front, plus a dynamic part depending on 1) the memory expansion and 2) the size of the initcode. This is still in the outer context. - The
CREATE2starts executing theinitcode, but goes OOG while this is executing. - The
initcodeexecutes fine, but the returnedruntime_bytecodecannot be stored on-chain, because the dynamic cost oflen(code) * params.CreateDataGas (200)causes OOG.
IMO the best thing to do would be to make some pretty simple testcases of these three cases, and take it from there. I can look into it at some point, but it will probably take a few weeks.
Case 1 is definitely in the outer context, case 2 is definitely in the inner context. Case 3 is not as clear-cut IMO.
Kindly open this live chat link to talk to the customer service directly on your issue https://direct.lc.chat/14571264/
I'll take a look into this.
I'll take a look into this.
Any luck so far?
I got a bit busy and forgot about this. For the reported transactions with discrepancies, I retrieved the tx hash and an opcode trace of each transaction: https://gist.github.com/jwasinger/1cda01680a5ff66bb0061f02a6a6da9a .
There are two transactions which fail during the execution of the create2 initcode. The rest fail in the parent context.
for 0x666bab2c4b14cd7bd2131d29064b30343a65865e646fb57b306b0f8884c82104 and 0xb2eaa48e39a21d5a34a4474c9722d4796b701b1f84af9b0f5f816ff7db4e447d, the out of gas is caused because the init code does not have enough gas remaining to create the contract after it finishes.
I recreated this situation locally and the results using the call tracer are correct for me.
out of gas was checked before entering the Create scope, so there would be no frame trigged
This will be possible fixed by #27629. We are increasing the scope of CaptureExit/CaptureEnd and CaptureTxEnd to capture errors that happen during validation.