visit
As developers, it’s important we understand what actually happens under the hood during an Ethereum transaction. Trying to debug, improve, or secure code often has limited visibility into exactly what happens when a smart contract executes. That’s where Ethereum Virtual Machine (EVM) traces come into play.
In this article, we’ll look at the type of data traces give you, how you can execute a trace, and options for tracing — manual, running archive nodes, and using the Infura Trace API.
Yes, you can use the transaction receipts to understand the basic info — status code, etc. — but there is still a lack of specific, detailed information that prevents you from totally understanding what happened and what steps you should take next to fix the issues when they inevitably arrive.
EVM traces are the critical piece that gives you missing information — reasons for failure, internal calls, interactions with other contracts, transfers of assets, etc.
With trace information, you can:
In short, you need traces when you need a granular understanding of what’s happening on Ethereum — situations like analysis, debugging Solidity, and improving security.
“The is an essential tool for Ethereum developers that provides the ability to gain deeper insights into the execution of smart contracts and transactions on Ethereum.
Developers can retrieve details from transaction data not logged on the blockchain, enabling them to debug, analyze, and perform other tasks and smart contract functions that require a granular understanding of transaction execution on Ethereum.”
There are five types of calls you can make to the Trace API:
Trace Transaction — Helps you understand what happened during a transaction (gas used, outputs, why it failed, etc). It’s great for optimizing performance. You provide the transaction hash and get back all the trace details.
Trace Block — Traces all transactions in a given block. Helps you to analyze overall blockchain behavior.
Trace Call — Gives you info on a specific call based on a transaction. You provide the to and from addresses and the block. Trace Call is a lot like Trace Transaction — except Trace Call also returns any state diff as well.
Trace Call Many — Just like the above, but traces multiple calls at once.
Trace Filter — You can provide a filter for specific parameters for what traces are returned, such as block #, to address, from address, etc). It can trace from block to block, or from address to address. Allows you to track wallets, contract activity, etc.
Let’s look at a quick example so you can see what it looks like in action. We’ll use the trace_transaction
call to trace .
Request:
curl --location '//mainnet.infura.io/v3/<INFURA API KEY> \
--header 'Content-Type: text/plain' \
--data '{ "id": 1, "method": "trace_transaction", "jsonrpc": "2.0", "params": ["0xeb852958eeb1d026b10c6ad3c995520364b83929e1e0908801194f5b680d54ea"] }'
Response:
{
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"action": {
"callType": "call",
"from": "0xeecc9674d3600e3feb1b01b9ff7c72ac2e1c560f",
"gas": "0x1a0c8",
"input": "0xe2bbb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037b1d9c38a24b27c",
"to": "0xfb063b1ae6471e6795d6ad1fc7f47c1cab1f3422",
"value": "0x0"
},
"blockHash": "0x89b3ee89b30133dfd67888bf0baeea58b8a52b1beb983efcc7aa771a3fd489af",
"blockNumber": 17370663,
"error": "out of gas",
"result": null,
"subtraces": 4,
"traceAddress": [],
"transactionHash": "0xeb852958eeb1d026b10c6ad3c995520364b83929e1e0908801194f5b680d54ea",
"transactionPosition": 110,
"type": "call"
},
. . .
}
This is a simple example — but you can see in the above that we’ve passed in a transaction hash and gotten back a trace for that transaction, including the reason it failed: out of gas. More complicated examples can return child traces, filtered results, and more.
Check out the docs and other tutorials .