6

This is a follow up from How to identify token transfers looking at a transaction?.

I have transaction that results in a transfer of tokens.

From PancakeSwap: Router v2
To 0xd423fde466315d45fb0da457df28d5eeb92be580
For 0.005 ($2.97) Wrapped BNB (WBNB)

From 0xd423fde466315d45fb0da457df28d5eeb92be580
To 0xb54eb0cc6457e9d74e20672d8961fad3cde4511c
For 0.154823285118196657 ($2.94) Bogged Finan... (BOG)

I can access transaction logs using getTransactionReceipt, e.g.

{
  blockHash: '0x7a3e03a2eaaf39ba85e5513205545d2509c24e8a58f03bb77d82f136f7028697',
  blockNumber: 7460735,
  contractAddress: null,
  cumulativeGasUsed: '39606975',
  from: '0xb54eb0cc6457e9d74e20672d8961fad3cde4511c',
  gasUsed: '292724',
  logs: [
    {
      address: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
      topics: [
        '0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c',
        '0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e'
      ],
      data: '0x0000000000000000000000000000000000000000000000000011c37937e08000',
      blockNumber: 7460735,
      transactionHash: '0xcf95271d63836f17c0c3a7beda7df2ea7029ce9161dc6808da86f5f9ce740830',
      transactionIndex: 265,
      blockHash: '0x7a3e03a2eaaf39ba85e5513205545d2509c24e8a58f03bb77d82f136f7028697',
      logIndex: 1007,
      removed: false,
      id: 'log_9d934f9a'
    },
    {
      address: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
      topics: [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e',
        '0x000000000000000000000000d423fde466315d45fb0da457df28d5eeb92be580'
      ],
      data: '0x0000000000000000000000000000000000000000000000000011c37937e08000',
      blockNumber: 7460735,
      transactionHash: '0xcf95271d63836f17c0c3a7beda7df2ea7029ce9161dc6808da86f5f9ce740830',
      transactionIndex: 265,
      blockHash: '0x7a3e03a2eaaf39ba85e5513205545d2509c24e8a58f03bb77d82f136f7028697',
      logIndex: 1008,
      removed: false,
      id: 'log_f759d019'
    },
    {
      address: '0xD7B729ef857Aa773f47D37088A1181bB3fbF0099',
      topics: [
        '0x63be20cc905d5ba0cf65db405c4999f99f2575e521875f13a8009d6eed7a09d9'
      ],
      data: '0x000000000000000000000000d423fde466315d45fb0da457df28d5eeb92be580000000000000000000000000000000000000000000000000000aa739b8dd5525',
      blockNumber: 7460735,
      transactionHash: '0xcf95271d63836f17c0c3a7beda7df2ea7029ce9161dc6808da86f5f9ce740830',
      transactionIndex: 265,
      blockHash: '0x7a3e03a2eaaf39ba85e5513205545d2509c24e8a58f03bb77d82f136f7028697',
      logIndex: 1009,
      removed: false,
      id: 'log_e07c5a40'
    },
    {
      address: '0xD7B729ef857Aa773f47D37088A1181bB3fbF0099',
      topics: [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x000000000000000000000000d423fde466315d45fb0da457df28d5eeb92be580',
        '0x000000000000000000000000b54eb0cc6457e9d74e20672d8961fad3cde4511c'
      ],
      data: '0x00000000000000000000000000000000000000000000000002260af5206ddbb1',
      blockNumber: 7460735,
      transactionHash: '0xcf95271d63836f17c0c3a7beda7df2ea7029ce9161dc6808da86f5f9ce740830',
      transactionIndex: 265,
      blockHash: '0x7a3e03a2eaaf39ba85e5513205545d2509c24e8a58f03bb77d82f136f7028697',
      logIndex: 1010,
      removed: false,
      id: 'log_4051d23e'
    },
    {
      address: '0xD423fDe466315D45fB0da457dF28D5EEB92be580',
      topics: [
        '0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1'
      ],
      data: '0x0000000000000000000000000000000000000000000000257558ffc7c1bb7c9d0000000000000000000000000000000000000000000004a14e4339975756b2ea',
      blockNumber: 7460735,
      transactionHash: '0xcf95271d63836f17c0c3a7beda7df2ea7029ce9161dc6808da86f5f9ce740830',
      transactionIndex: 265,
      blockHash: '0x7a3e03a2eaaf39ba85e5513205545d2509c24e8a58f03bb77d82f136f7028697',
      logIndex: 1011,
      removed: false,
      id: 'log_382fd81b'
    },
    {
      address: '0xD423fDe466315D45fB0da457dF28D5EEB92be580',
      topics: [
        '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822',
        '0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e',
        '0x000000000000000000000000b54eb0cc6457e9d74e20672d8961fad3cde4511c'
      ],
      data: '0x0000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000000aa739b8dd552600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000230b22ed94b30d7',
      blockNumber: 7460735,
      transactionHash: '0xcf95271d63836f17c0c3a7beda7df2ea7029ce9161dc6808da86f5f9ce740830',
      transactionIndex: 265,
      blockHash: '0x7a3e03a2eaaf39ba85e5513205545d2509c24e8a58f03bb77d82f136f7028697',
      logIndex: 1012,
      removed: false,
      id: 'log_abf4a762'
    }
  ],
  logsBloom: '0x002002000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000020400000000000000000000000000401000000000008000080000002000000000000000000004000080000000100000000000000002000000000000000000000000000000000000100000000000000000000000000040000000000000002400010000000800000040000000000000000c0000000000000000020000000000000000000400000000000000000000000002000000000000000000020080000000000000001000000000000080000080000000000000020000000000000000000000000000400000000000000000',
  status: true,
  to: '0x10ed43c718714eb63d5aa57b78b54704e256024e',
  transactionHash: '0xcf95271d63836f17c0c3a7beda7df2ea7029ce9161dc6808da86f5f9ce740830',
  transactionIndex: 265
}

As is, events are not readable; I need to decode them, and as far as I understand, I should be using web3.eth.abi.decodeLog(inputs, hexString, topics). However, I am not clear on how do I get the inputs value.

As far as I understand, it needs to be ABI of the contract that produced the event, e.g. In case of event:

{
  address: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
  topics: [
    '0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c',
    '0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e'
  ],
  data: '0x0000000000000000000000000000000000000000000000000011c37937e08000',
  blockNumber: 7460735,
  transactionHash: '0xcf95271d63836f17c0c3a7beda7df2ea7029ce9161dc6808da86f5f9ce740830',
  transactionIndex: 265,
  blockHash: '0x7a3e03a2eaaf39ba85e5513205545d2509c24e8a58f03bb77d82f136f7028697',
  logIndex: 1007,
  removed: false,
  id: 'log_9d934f9a'
}

I need to get ABI of contract 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c.

I have tried:

web3.eth.abi.decodeLog(
  abi,
  '0x0000000000000000000000000000000000000000000000000011c37937e08000',
  [
    '0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c',
    '0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e',
  ],
);

However, this produced error:

Error: invalid type (argument="type", value="_factory", code=INVALID_ARGUMENT, version=abi/5.0.7)

It seems like I am providing wrong value.

How do I know what ABI do I use to decode this log?

4

1 Answer 1

3

This isn't a complete answer, but here is what I have so far.

If you look at the contract 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c code, it looks like it implements BEP20 interface. I don't know how to determine this programmatically, but that seems to be the case.

I looked up BEP20 ABI and used it to construct web3.eth.Contract.

const contract = new web3.eth.Contract(bep20, '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c');

I then extracted ABI tokens that describe events:

const knownEventTokens = contract.options.jsonInterface.filter((token) => {
  return token.type === 'event';
});

If you explore the value of knownEventTokens, tokens now have a signature property:

[
  {
    anonymous: false,
    inputs: [
      { indexed: true, name: 'owner', type: 'address' },
      { indexed: true, name: 'spender', type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' }
    ],
    name: 'Approval',
    type: 'event',
    constant: undefined,
    payable: undefined,
    signature: '0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925'
  },
  {
    anonymous: false,
    inputs: [
      { indexed: true, name: 'from', type: 'address' },
      { indexed: true, name: 'to', type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' }
    ],
    name: 'Transfer',
    type: 'event',
    constant: undefined,
    payable: undefined,
    signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
  }
]

As far as I can tell, as long as the signature matches the first topic in a log event, then the inputs can be used to decode log event values, e.g.

const events = [
  {
    address: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
    blockHash: '0xbeecdeddd358fca1df274a2545ce5b55cf1938faa377b11c0f78c638d4734868',
    blockNumber: 7_463_306,
    data: '0x000000000000000000000000000000000000000000000000002386f26fc10000',
    id: 'log_041e02ed',
    logIndex: 143,
    removed: false,
    topics: [
      '0xe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c',
      '0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e',
    ],
    transactionHash: '0xea00edb3e568701901b56c37c4b185be66dd5bc6398cf3f9298e8542091421f1',
    transactionIndex: 53,
  },
  {
    address: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
    blockHash: '0xbeecdeddd358fca1df274a2545ce5b55cf1938faa377b11c0f78c638d4734868',
    blockNumber: 7_463_306,
    data: '0x000000000000000000000000000000000000000000000000002386f26fc10000',
    id: 'log_cdebb74e',
    logIndex: 144,
    removed: false,
    topics: [
      '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      '0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e',
      '0x000000000000000000000000ed726e312afd8f856ab96170fd7225c8cb731f05',
    ],
    transactionHash: '0xea00edb3e568701901b56c37c4b185be66dd5bc6398cf3f9298e8542091421f1',
    transactionIndex: 53,
  },
  {
    address: '0xA528Ed9059e3D418324371C011b7bff8a1c838EB',
    blockHash: '0xbeecdeddd358fca1df274a2545ce5b55cf1938faa377b11c0f78c638d4734868',
    blockNumber: 7_463_306,
    data: '0x0000000000000000000000000000000000000000000000de45e400f02a502361',
    id: 'log_b6e3762a',
    logIndex: 145,
    removed: false,
    topics: [
      '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      '0x000000000000000000000000ed726e312afd8f856ab96170fd7225c8cb731f05',
      '0x0000000000000000000000008e622e3c0c46b20e96ce61e3ce0180fd2fb5baa2',
    ],
    transactionHash: '0xea00edb3e568701901b56c37c4b185be66dd5bc6398cf3f9298e8542091421f1',
    transactionIndex: 53,
  },
  {
    address: '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    blockHash: '0xbeecdeddd358fca1df274a2545ce5b55cf1938faa377b11c0f78c638d4734868',
    blockNumber: 7_463_306,
    data: '0x00000000000000000000000000000000000000000000ca2de3365dab3b230ce40000000000000000000000000000000000000000000000001d24b2dfac520000',
    id: 'log_5e101161',
    logIndex: 146,
    removed: false,
    topics: [
      '0x1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1',
    ],
    transactionHash: '0xea00edb3e568701901b56c37c4b185be66dd5bc6398cf3f9298e8542091421f1',
    transactionIndex: 53,
  },
  {
    address: '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    blockHash: '0xbeecdeddd358fca1df274a2545ce5b55cf1938faa377b11c0f78c638d4734868',
    blockNumber: 7_463_306,
    data: '0x00000000000000000000000000000000000000000000000bca378b643e734cc5000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000f6f852abb584590add0000000000000000000000000000000000000000000000000000000000000000',
    id: 'log_1b3a7700',
    logIndex: 147,
    removed: false,
    topics: [
      '0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822',
      '0x00000000000000000000000010ed43c718714eb63d5aa57b78b54704e256024e',
      '0x0000000000000000000000008e622e3c0c46b20e96ce61e3ce0180fd2fb5baa2',
    ],
    transactionHash: '0xea00edb3e568701901b56c37c4b185be66dd5bc6398cf3f9298e8542091421f1',
    transactionIndex: 53,
  },
];

for (const event of events) {
  const eventToken = knownEventTokens.find((knownEventToken) => {
    return knownEventToken.signature === event.topics[0];
  });

  if (!eventToken) {
    console.log('cannot process log %d', event.logIndex);

    continue;
  }

  console.log({
    eventToken,
    values: web3.eth.abi.decodeLog(
      eventToken.inputs,
      event.data,
      event.topics.slice(1),
    ),
  });
}

Which gives:

cannot process log 143
{
  eventToken: {
    anonymous: false,
    inputs: [
      { indexed: true, name: 'from', type: 'address' },
      { indexed: true, name: 'to', type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' }
    ],
    name: 'Transfer',
    type: 'event',
    constant: undefined,
    payable: undefined,
    signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
  },
  values: Result {
    '0': '0x10ED43C718714eb63d5aA57B78B54704E256024E',
    '1': '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    '2': '10000000000000000',
    __length__: 3,
    from: '0x10ED43C718714eb63d5aA57B78B54704E256024E',
    to: '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    value: '10000000000000000'
  }
}
{
  eventToken: {
    anonymous: false,
    inputs: [
      { indexed: true, name: 'from', type: 'address' },
      { indexed: true, name: 'to', type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' }
    ],
    name: 'Transfer',
    type: 'event',
    constant: undefined,
    payable: undefined,
    signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
  },
  values: Result {
    '0': '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    '1': '0x8e622e3c0c46B20e96cE61E3Ce0180Fd2fb5bAA2',
    '2': '4100213335678329561953',
    __length__: 3,
    from: '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    to: '0x8e622e3c0c46B20e96cE61E3Ce0180Fd2fb5bAA2',
    value: '4100213335678329561953'
  }
}
cannot process log 146
cannot process log 147
https://quiet-black-snowflake.bsc.quiknode.pro/3650b4c6695bbc00b5aaf2bbc6bf794e447538a2/
(node:75758) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
^[[A^C
gke_applaudience_europe-west4-c_juice-boost (dxcoin) in dxcoin-api on master [$✘!+?] took 6m31s
12:18:41 ➜ babel-node src/bin/test.js | roarr
[
  {
    anonymous: false,
    inputs: [
      { indexed: true, name: 'owner', type: 'address' },
      { indexed: true, name: 'spender', type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' }
    ],
    name: 'Approval',
    type: 'event',
    constant: undefined,
    payable: undefined,
    signature: '0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925'
  },
  {
    anonymous: false,
    inputs: [
      { indexed: true, name: 'from', type: 'address' },
      { indexed: true, name: 'to', type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' }
    ],
    name: 'Transfer',
    type: 'event',
    constant: undefined,
    payable: undefined,
    signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
  }
]
cannot process log 143
{
  eventToken: {
    anonymous: false,
    inputs: [
      { indexed: true, name: 'from', type: 'address' },
      { indexed: true, name: 'to', type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' }
    ],
    name: 'Transfer',
    type: 'event',
    constant: undefined,
    payable: undefined,
    signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
  },
  values: Result {
    '0': '0x10ED43C718714eb63d5aA57B78B54704E256024E',
    '1': '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    '2': '10000000000000000',
    __length__: 3,
    from: '0x10ED43C718714eb63d5aA57B78B54704E256024E',
    to: '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    value: '10000000000000000'
  }
}
{
  eventToken: {
    anonymous: false,
    inputs: [
      { indexed: true, name: 'from', type: 'address' },
      { indexed: true, name: 'to', type: 'address' },
      { indexed: false, name: 'value', type: 'uint256' }
    ],
    name: 'Transfer',
    type: 'event',
    constant: undefined,
    payable: undefined,
    signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'
  },
  values: Result {
    '0': '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    '1': '0x8e622e3c0c46B20e96cE61E3Ce0180Fd2fb5bAA2',
    '2': '4100213335678329561953',
    __length__: 3,
    from: '0xeD726e312AfD8f856AB96170fd7225c8cb731f05',
    to: '0x8e622e3c0c46B20e96cE61E3Ce0180Fd2fb5bAA2',
    value: '4100213335678329561953'
  }
}

This is good enough for my use case. However, I do not understand how:

  1. How would one know which contract to use when processing an arbitrary event?
  2. In our case, we cannot process some log events. It seems like those events are not covered by BEP20. How do I find how to process them?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.