How to read Event's log from transaction receipt with Web3.js?

10.1k views Asked by At

I have implement function in my solidity project and it log some event with event name 'NewRound' that I want to get value from it to save in my centralize database after I send transaction I got receipt look like this.

{
  blockHash: '0x8df078a04e47cbe4ea7e58626ffc894f0d7b2620e821f9432aa1c03b3431d480',
  blockNumber: 19125457,
  contractAddress: null,
  cumulativeGasUsed: 995561,
  from: '0x0c46c078196461b17f7e1e652004bd7ee448ed49',
  gasUsed: 116384,
  logs: [
    {
      address: '0xc032d238fd4deD8A8AB97a8983AE3B51ccfa8fd3',
      topics: [Array],
      data: '0x',
      blockNumber: 19125457,
      transactionHash: '0x1e13744ddaf81cb3ca7a9cbd98ca6b2ede51a22d7e2795305b2621d59a0b9ac1',
      transactionIndex: 5,
      blockHash: '0x8df078a04e47cbe4ea7e58626ffc894f0d7b2620e821f9432aa1c03b3431d480',
      logIndex: 7,
      removed: false,
      id: 'log_301e03cb'
    }
  ],
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000040000800000000020000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000',
  status: true,
  to: '0xc032d238fd4ded8a8ab97a8983ae3b51ccfa8fd3',
  transactionHash: '0x1e13744ddaf81cb3ca7a9cbd98ca6b2ede51a22d7e2795305b2621d59a0b9ac1',
  transactionIndex: 5,
  type: '0x0'
}

My log data is in topics params.But I have no idea how to decode it.Has anyone ever do something like this ?

My event data. enter image description here

5

There are 5 answers

2
Petr Hejda On

The topics[0] field always stores the event signature hash. It's a keccak-256 hash of the event name, followed by parameter datatypes in parentheses.

In your case, that's hash of the string NewRound(uint256).

Following items of the topics array are indexed parameters of the event. And the last topics item is all unindexed parameters concatenated (which doesn't apply to your case, as there are no unindexed parameters).

These items are ABI encoded and represented in hex.

Assuming you have the ABI JSON of the contract that emitted the event, you can decode the values using the web3.eth.abi.decodeLog() function.

0
BitOfUniverse On

For non-anonymous (most of the cases) events use:

const decoded = web3.eth.abi.decodeLog(EVENT_ABI, event.data, event.topics.slice(1));
console.log(decoded);

otherwise, use:

const decoded = web3.eth.abi.decodeLog(EVENT_ABI, event.data, event.topics);
console.log(decoded);

Full example:

const TOPIC = web3.eth.abi.encodeEventSignature('Event(uint256,bytes32)');
const EVENT_ABI = []; // your event ABI here 

const subscription = web3.eth.subscribe("logs", { topics: [TOPIC] });
subscription.on("data", (event) => { 
  const decoded = web3.eth.abi.decodeLog(EVENT_ABI, event.data, 
  event.topics.slice(1));
  console.log(decoded);

} );
0
Numant Santz On

This library is pretty helpful with decoding Transaction Receipt Logs. Just need to load the contract ABI manually and decode using the provided objects

0
Anthony Sychev On

Source: https://community.infura.io/t/web3-js-how-to-track-nft-erc-721-1155-transfers-and-mints-specific-address-nft/5500

Implementation example for ERC1155:

...
const contract = new web3.eth.Contract(ABI_ARRAY, "0xContractAddress");


let events = await cont.get("0x1e13744ddaf81cb3ca7a9cbd98ca6b2ede51a22d7e2795305b2621d59a0b9ac1")
//or

let events = await contract.getPastEvents(...); // -> you have your response like this
/*
{
  blockHash: '0x8df078a04e47cbe4ea7e58626ffc894f0d7b2620e821f9432aa1c03b3431d480',
  blockNumber: 19125457,
  contractAddress: null,
  cumulativeGasUsed: 995561,
  from: '0x0c46c078196461b17f7e1e652004bd7ee448ed49',
  gasUsed: 116384,
  logs: [
    {
      address: '0xc032d238fd4deD8A8AB97a8983AE3B51ccfa8fd3',
      topics: [Array],
      data: '0x',
      blockNumber: 19125457,
      transactionHash: '0x1e13744ddaf81cb3ca7a9cbd98ca6b2ede51a22d7e2795305b2621d59a0b9ac1',
      transactionIndex: 5,
      blockHash: '0x8df078a04e47cbe4ea7e58626ffc894f0d7b2620e821f9432aa1c03b3431d480',
      logIndex: 7,
      removed: false,
      id: 'log_301e03cb'
    }
  ],
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000040000800000000020000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000',
  status: true,
  to: '0xc032d238fd4ded8a8ab97a8983ae3b51ccfa8fd3',
  transactionHash: '0x1e13744ddaf81cb3ca7a9cbd98ca6b2ede51a22d7e2795305b2621d59a0b9ac1',
  transactionIndex: 5,
  type: '0x0'
}
*/

let transaction = web3.eth.abi.decodeLog(
    [
        {
            type: "address",
            name: "operator",
            indexed: true,
        },
        {
            type: "address",
            name: "from",
            indexed: true,
        },
        {
            type: "address",
            name: "to",
            indexed: true,
        },
        {
            type: "uint256",
            name: "id",
        },
        {
            type: "uint256",
            name: "value",
        },
    ],
    events.logs.data,
    [events.logs.topics[1], events.logs.topics[2], events.logs.topics[3]]
);

console.log(
    `\n` +
        `New ERC-1155 transaction found in block ${events.logs.blockNumber} with hash ${event.logs.transactionHash}\n` +
        `Operator: ${transaction.operator}\n` +
        `From: ${
            transaction.from === "0x0000000000000000000000000000000000000000"
                ? "New mint!"
                : transaction.from
        }\n` +
        `To: ${transaction.to}\n` +
        `id: ${transaction.id}\n` +
        `value: ${transaction.value}`
);

for ERC721 last part :

let transaction = web3.eth.abi.decodeLog(
    [
        {
            type: "address",
            name: "from",
            indexed: true,
        },
        {
            type: "address",
            name: "to",
            indexed: true,
        },
        {
            type: "uint256",
            name: "tokenId",
            indexed: true,
        },
    ],
    events.log.data,
    events.log.topics
);

console.log(
    `\n` +
        `New ERC-712 transaction found in block ${events.log.blockNumber} with hash ${events.log.transactionHash}\n` +
        `From: ${
            transaction.from ===
            "0x0000000000000000000000000000000000000000"
                ? "New mint!"
                : transaction.from
        }\n` +
        `To: ${transaction.to}\n` +
        `Token contract: ${events.log.address}\n` +
        `Token ID: ${transaction.tokenId}`
);

Regards

0
Senuda Jayalath On

The data field will contain all the unindexed parameters of the given event. To decode that you can use web3.eth.abi.decodeLog(inputs, hexString, topics) as shown here.
You can get the name of the event from the first element of the field topics (i.e topics[0]). The first element here corresponds to the keccak256 of the event signature. web3.utils.sha3(string) can be used to to hash your event signature to check if the first entry of topics array match. More info here.
If your event has indexed parameters, they can be found from the rest of the entries of the the topics array. To convert then to human readable form, follow the same steps as you did to decode the element in data field.