trace_transaction | Polygon

Polygon API method that traces a specific transaction. It provides a detailed record of all the steps taken by the Ethereum Virtual Machine (EVM) during the execution, including all the operations performed and the changes made to the blockchain state. This method is available on Erigon only.

👍

Get you own node endpoint today

Start for free and get your app to production levels immediately. No credit card required.

You can sign up with your GitHub, X, Google, or Microsoft account.

Enable the Erigon client on your elastic Polygon node

📘

Available on the Business subscription plan and higher.

Once you have joined a public network, do the following:

  1. Select the project with the network.
  2. Select the network.
  3. Click Add node.
  4. Provide a node name.
  5. Under Type, select Elastic.
  6. Under Mode, select Archive. With an archive node, you will be able to query historical states for the entire chain.
  7. Under Debug and trace APIs, select On.
  8. Under Hosting, select Chainstack.
  9. For Chainstack hosting, select a cloud provider and a region.
  10. Review your changes and click Add node.

Once deployed, the node status will change from Pending to Running. You will also see the Debug and trace tag next to the node name.

Enable the Erigon client on your dedicated Polygon node

📘

Available on the Growth subscription plan and higher.

Once you have joined a public network, do the following:

  1. Select the project with the network.
  2. Select the network.
  3. Click Add node.
  4. Provide a node name.
  5. Under Type, select Dedicated.
  6. Under Mode, select Archive. With an archive node, you will be able to query historical states for the entire chain.
  7. Under Hosting, select Chainstack. See Supported hosting options.
  8. For Chainstack hosting, select a cloud provider and a region.
  9. Under Client, select Erigon.
  10. Review your changes and click Send request.

The Chainstack Sales team will reach out to your shortly.

Parameters

  • hash — the hash identifying a transaction

Response

  • action — an object that describes the action taken by the transaction:
    • from — the address of the sender who initiated the transaction.
    • callType — the type of call, call or delegatecall, two ways to invoke a function in a smart contract. call creates a new environment for the function to work in, so changes made in that function won't affect the environment where the function was called. delegatecall doesn't create a new environment. Instead, it runs the function within the environment of the caller, so changes made in that function will affect the caller's environment.
    • gas — the units of gas included in the transaction by the sender.
    • input — the optional input data sent with the transaction, usually used to interact with smart contracts.
    • to — the address of the recipient of the transaction if it was a transaction to an address. For contract creation transactions, this field is null.
    • value — the value of the native token transferred along with the transaction, in Wei.
    • blockHash — the hash of the block in which the transaction was included.
    • blockNumber — the number of the block in which the transaction was included.
    • error — a string that indicates whether the transaction was successful or not. null if successful, Reverted if not.
    • result — an object that contains additional data about the execution of the transaction:
      • gasUsed — the total used gas by the call, encoded as hexadecimal.
      • output — the return value of the call, encoded as a hexadecimal string.
    • subtraces — the number of sub-traces created during execution. When a transaction is executed on the EVM, it may trigger additional sub-executions, such as when a smart contract calls another smart contract or when an external account is accessed.
    • traceAddress — an array that indicates the position of the transaction in the trace.
    • transactionHash — the hash of the transaction.
    • transactionPosition — the position of the transaction in the block.
    • type — the type of action taken by the transaction, call or create. call is the most common type of trace and occurs when a smart contract invokes another contract's function. create represents the creation of a new smart contract. This type of trace occurs when a smart contract is deployed to the blockchain.

trace_transaction code examples

const Web3 = require("web3");
const NODE_URL = "CHAINSTACK_NODE_URL";
const web3 = new Web3(NODE_URL);

// Define the trace_transaction custom method
web3.extend({
  property: 'debug',
  methods: [{
    name: 'traceTransaction',
    call: 'trace_transaction',
    params: 1,
    inputFormatter: [web3.extend.formatters.inputHashFormatter],
    outputFormatter: web3.extend.formatters.outputCallFormatter
  }]
});

async function traceTransaction(txHash) {
    const result = await web3.debug.traceTransaction(txHash);
    console.log(result);
}

traceTransaction("0x9c43baea5c33916b282707506db6d4e79e9e13d96fec1028493bd2ec2da66fd0");
const ethers = require('ethers');
const NODE_URL = "CHAINSTACK_NODE_URL";
const provider = new ethers.JsonRpcProvider(NODE_URL);

const traceTransaction = async (txHash) => {
  const traces = await provider.send("trace_transaction", [txHash]);
  console.log(traces);
};

traceTransaction("0x9c43baea5c33916b282707506db6d4e79e9e13d96fec1028493bd2ec2da66fd0")
from web3 import Web3  
node_url = "CHAINSTACK_NODE_URL" 
web3 = Web3.HTTPProvider(node_url)

tx_hash = "0x9c43baea5c33916b282707506db6d4e79e9e13d96fec1028493bd2ec2da66fd0"

traces = web3.provider.make_request('trace_transaction', [tx_hash])
print(traces)

Use case

A practical use case of the trace_transaction method can be in inspecting NFT transfers, allowing you to identify internal transactions, the sender and receiver, and the amounts transferred. This can be especially useful when analyzing an ERC-721 token purchase on a marketplace like Opensea, where the transfer of funds is not always straightforward due to multiple internal calls for transferring funds to the NFT owner, paying royalties to the creator, and other factors. By using trace_transaction, you can gain a more comprehensive understanding of the transaction flow.

The following is an implementation of the logic using web3.js inspecting an ERC-721 transfer from Opensea on Polygon:

const Web3 = require("web3");
const NODE_URL = "CHAINSTACK_NODE_URL";
const web3 = new Web3(NODE_URL);

// Define the trace_transaction custom method
web3.extend({
  property: 'debug',
  methods: [{
    name: 'traceTransaction',
    call: 'trace_transaction',
    params: 1,
    inputFormatter: [web3.extend.formatters.inputHashFormatter],
    outputFormatter: web3.extend.formatters.outputCallFormatter
  }]
});

// Trace a transaction using the web3.debug.traceTransaction method
async function traceTransaction(txHash) {
  const result = await web3.debug.traceTransaction(txHash);
  return result.map(({ action }) => action);
}

// Parse a value in wei to ether
function parseValue(wei) {
  const bigNumber = web3.utils.toBN(wei);
  const decimalString = bigNumber.toString();
  const etherValue = web3.utils.fromWei(decimalString);
  return etherValue;
}

// Main function to run the program
async function main() {
  const txHash = "0xe2eb8be0ea71220bc298e48ba58034d49efb2d311ca45dfe228cb564cd8a3fb5";
  const transactionTraces = await traceTransaction(txHash); // Trace the specified transaction
  const extractedData = transactionTraces.map(({ from, to, value }) => ({ from, to, value })); // Extract relevant data from the transaction trace

  // Loop through each extracted data object and print relevant information
  for (const { from, to, value } of extractedData) {
    const parsedValue = parseValue(value); // Parse the value to ether

    // Print information about non-zero value transfers
    if (parsedValue !== '0') {
      console.log('===== Call =====');
      console.log(`From address: ${from}`);
      console.log(`To address: ${to}`);
      console.log(`Value of ${parsedValue} MATIC\n`);
    }
  }
}

main(); // Call the main function to start the program

A custom method called traceTransaction is defined using the extend method in web3.js. This method is used to trace the execution of a Polygon transaction and returns an array of actions that occurred during its execution.

The parseValue function is defined to convert the value from Wei (the smallest denomination of ether) to its equivalent ether value.

Finally, the main function is defined, which traces the specified Polygon transaction using the traceTransaction method extracts relevant data from the transaction trace, parses the transaction value to ether using the parseValue function, and prints information about non-zero value transfers that occurred during the transaction execution.

In this case, the program extracts the sender, receiver, and value of each call. This allows to understand that the first two transfers are some kind of royalty fee, and the last transfer is the seller of the NFT receiving the amount.

===== Call =====
From address: 0xb848a33cd484b9fbdca4593c3bc03ae6015c5b94
To address: 0x00000000006c3852cbef3e08e8df289169ede581  
Value of 20 MATIC

===== Call =====
From address: 0x00000000006c3852cbef3e08e8df289169ede581
To address: 0x0000a26b00c1f0df003000390027140000faa719  
Value of 0.5 MATIC

===== Call =====
From address: 0x00000000006c3852cbef3e08e8df289169ede581
To address: 0xa52944e9fe7bf9d3d515af1494738ea7d4fa2dea
Value of 0.6 MATIC

===== Call =====
From address: 0x00000000006c3852cbef3e08e8df289169ede581
To address: 0x11c6fef26abb8dfee23c2df67e9e60d120a48413
Value of 18.9 MATIC

From this, we can see that address 0xb848a33cd484b9fbdca4593c3bc03ae6015c5b94 pays 20 MATIC to buy an NFT, fees of 0.5 and 0.6 MATIC are taken from the total amount, and the seller 0x11c6fef26abb8dfee23c2df67e9e60d120a48413 receives 18.9 MATIC. The next step could be to find out what Token ID is bought during this transaction. This information is not readily available in the trace_transaction response. If you dig, you can find it in the input field of one of the calls, but it is encoded. The best solution is to run the same transaction hash using eth_getTransactionReceipt and decode the logs.

📘

Read Tracking some Bored Apes: The Ethereum event logs tutorial to learn how to read and decode event logs.

Try the trace_transaction RPC method yourself

Language
Click Try It! to start a request and see the response here!