Skip to content

This repo describes the debug_traceTransaction method, which is available by querying a node running Erigon or Go Ethereum if the debug module is enabled.

License

Notifications You must be signed in to change notification settings

akegaviar/Erigon-Geth-debug_traceTransaction-guide

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

Erigon-Geth-debug_traceTransaction-guide

This repo describes the debug_traceTransaction method, which is available by querying a node running Erigon or Go Ethereum if the debug module is enabled.

debug_traceTransaction guide

The debug function in Erigon is very useful during the development of a smart contract to understand why a transaction is failing.

debug_traceTransaction returns logs of low-level opcode that can be used to show what happens step by step during the process and what is the reason for it failing.

Developers can use this data to show the steps happening during a transaction.

In this guide we will see three ways to analyze a failed transaction:

  1. Using Geth VM Debug Trace Transaction page on Etherscan.
  2. Using tenderly.co, an Ethereum developer platform.
  3. Calling the debug_traceTransaction method.

debug_traceTransaction method— parameters accepted and returned

Parameters:

transaction hash - Hash of the transaction to trace.

Returns:

array - Block traces.

  • result - Transaction Trace Object, with the following fields:

    • failed - Boolean.

    • gas - Quantity.

    • returnvalue - Data.

    • structlogs - Array:

      • entries - Array.

      • storagesbydepth - Array.

Code examples

cURL

curl -X POST 'ERIGON_NODE_URL' \
-H 'Content-Type: application/json' \
--data '{"method": "debug_traceTransaction", "params": ["0x1cd5d6379c7a06619acaf07a1a87116e5a476203b1798862ebb7144ecc5ebba9", {}],"id":1,"jsonrpc":"2.0"}'

web3.py

from web3 import Web3

node_url = "ERIGON_NODE_URL"

# Create the node connection
web3 = Web3.HTTPProvider(node_url)

# print debug trace transaction
debug = web3.make_request('debug_traceTransaction', ['0x1cd5d6379c7a06619acaf07a1a87116e5a476203b1798862ebb7144ecc5ebba9'])
#print(result)  # print raw result

# Parse the result in a more readable way
for action in debug['result']['structLogs']:
    for key, val in action.items():
        print(key +':', val)

Analyze a failed transaction

Note: you will need access to an Ethereum node running Erigon to call the debug_traceTransaction method. You can get one with Chainstack.

Let's analyze this transaction:

This transaction is made by an account to a smart contract, and you can see that it failed and was reverted.

image

The transaction sends this data to the smart contract (calls the transfer function):

Function: transfer(address _to, uint256 _value)

MethodID: 0xa9059cbb
[0]:  000000000000000000000000876eabf441b2ee5b5b0554fd502a8e0600950cfa
[1]:  000000000000000000000000000000000000000000000000000005e5ac845ea0

raw data:

0xa9059cbb000000000000000000000000876eabf441b2ee5b5b0554fd502a8e0600950cfa000000000000000000000000000000000000000000000000000005e5ac845ea0

There are different ways to analyze the transaction.

Geth VM Debug Trace Transaction on Etherscan

The first option is from the Geth VM Trace Transaction page on Etherscan.

This is essentially the same output that you would get by calling debug_traceTransaction, but parsed nicely.

image

You can notice that the last operation is *REVERT at the step [241] and program counter (PC) 7243.

image

So this allows us to see that the transaction reverted for some reason, but we cannot see what that reason is.

Use tenderly.co

tenderly.co is a Ethereum developer platform with deep functionality across debugging, testing, infra and more. This platform allows us to really analyze a transaction.

If we use the transaction hash to in the dashboard we can retrieve the data. In the overview tab we can already see what the problem is.

link to the transaction overview in tenderly

This shows us that the transaction was reverted because the account calling the transfer function does not meet the condition of the modifier. In this case, the address sending the transaction (msg.sender) is not present in the whitelist mapping.

image

Then, if we go to the Debugger section, we can see the details, and you will notice that it shows the OPCODE that we retrieve if we call the debug_traceTransaction method.

It first shows the function that was called, with its relative OPCODE. As well as the contract, caller, and input information. Notice that in this case, the information is already converted into decimal from HEX.

image

Stack trace information:

{
  "[FUNCTION]": "transfer",
  "[OPCODE]": "JUMPDEST",
  "contract": {
    "address": "0xee4458e052b533b1aabd493b5f8c4d85d7b263dc",
    "balance": "0"
  },
  "caller": {
    "address": "0x7e6f723fcb32bafc4131f710d342c3d051b280ee",
    "balance": "12957438303317436"
  },
  "input": {
    "_to": "0x876eabf441b2ee5b5b0554fd502a8e0600950cfa",
    "_value": "6484000005792"
  },
  "[OUTPUT]": "0x",
  "[ERROR]": "execution reverted",
  "gas": {
    "gas_left": 128380,
    "gas_used": 5231,
    "total_gas_used": 21620
  }
}

The second step shows us why the transaction was reverted. It does not meet the condition of the whitelist modifier.

image

With its stack trace:

{
  "[FUNCTION]": "transfer",
  "[OPCODE]": "REVERT",
  "[INPUT]": "0x",
  "[OUTPUT]": "0x",
  "[ERROR]": "execution reverted",
  "gas": {
    "gas_left": 0,
    "gas_used": 0,
    "total_gas_used": 150000
  }
}

Call debug_traceTransaction :

Now calling debug_traceTransaction (from Postman), we can analyze what happens:

curl -X POST 'ERIGON_NODE_URL' \
-H 'Content-Type: application/json' \
--data '{"method": "debug_traceTransaction", "params": ["0x1cd5d6379c7a06619acaf07a1a87116e5a476203b1798862ebb7144ecc5ebba9", {}],"id":1,"jsonrpc":"2.0"}'

Here is the beginning of the response that you will receive by running the code above:

{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "structLogs": [
            {
                "pc": 0,
                "op": "PUSH1",
                "gas": 128380,
                "gasCost": 3,
                "depth": 1,
                "stack": [],
                "memory": []
            },
            {
                "pc": 2,
                "op": "PUSH1",
                "gas": 128377,
                "gasCost": 3,
                "depth": 1,
                "stack": [
                    "0x80"
                ],
                "memory": []
            },
            ...

You can see the full response in the debug_trace_response.json file in this Gist. It contains more than 5000 lines, and having it as a separate file keeps this guide a bit cleaner.

Then, you will find the REVERT opcode at the end, where it describes the error:

{
                "pc": 7243,
                "op": "REVERT",
                "gas": 123149,
                "gasCost": 0,
                "depth": 1,
                "stack": [
                    "0xa9059cbb",
                    "0x96d",
                    "0x876eabf441b2ee5b5b0554fd502a8e0600950cfa",
                    "0x5e5ac845ea0",
                    "0x0",
                    "0x0",
                    "0x0"
                ],
                "memory": [
                    "0000000000000000000000007e6f723fcb32bafc4131f710d342c3d051b280ee",
                    "0000000000000000000000000000000000000000000000000000000000000008",
                    "0000000000000000000000000000000000000000000000000000000000000080"
                ]
            }

By decoding these parameters, we can understand why the transaction fails.

Still working on a way to decode this. I assume that it shows on what line of the smart contract is reverted. But I can't find a way to decode it.

About

This repo describes the debug_traceTransaction method, which is available by querying a node running Erigon or Go Ethereum if the debug module is enabled.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published