3

I am trying to gather all events of a specific type on the entire chain, regardless of what contract emitted them.

When trying to find solutions online, I came across code like the following (source):

const filterId = await provider.send('eth_newFilter', [{
  address: ['0x123..', '0x456...'],
  fromBlock, toBlock, topics
}])

const logs = await provider.send('eth_getFilterChanges', [filterId]);

Here, multiple contract addresses can be stated. This, however, is not what I am looking for as I do not know the addresses of the contracts that emitted the events I am trying to gather.

I am looking for a version of the following code that gives me historical events, not events that are just coming in:

const provider = new ethers.providers.Web3Provider(window.ethereum);
const filter = {
  address: null,
  topics: [
    ethers.utils.id('MyEvent(address)')
  ]
};
provider.on(filter, event => {
  console.log(event);
});

Note that setting address to null means that the contract's address is not a criterion, i.e. I am accepting events regardless of the address of the contract that emitted it.

I would prefer a solution using ethers.js but a low-level solution using an explicit RPC call or a solution using a different library would also be fine.


Edit: I have tried to combine the two code blocks above as follows:

const filter = {
  address: null,
  topics: [
    ethers.utils.id('MyEvent(address)')
  ]
};
const filterId = await provider.send('eth_newFilter', [{
  address: null,
  fromBlock: '0x11',
  toBlock: '0x9819f0',
  topics: filter.topics,
}]);
const logs = await provider.send('eth_getFilterChanges', [filterId]);
console.log(logs);

However, this always yields the empty array.


Edit 2:

The following code is based on an answer:

const filter0 = {
  address: null,
  topics: [
    ethers.utils.id('MyEvent(address)')
  ]
};
const filter12 = myContract.filters.MyEvent();

const response0 = await provider.getLogs(filter0);
const response1 = await provider.getLogs(filter12);
const response2 = await myContract.queryFilter(filter12);

console.log('response0', response0);
console.log('response1', response1);
console.log('response2', response2);
console.log(filter12);

However, response0 and response1 are the empty array. Only response2 contains an event. I used a contract that was recently deployed and that only ever emitted 1 event of the specified kind. From the output of the filter, I can see that filter12 is indeed restricted to the correct address, so I do not understand why even response1 was empty.

1 Answer 1

3

Did you try using eth_getLogs. This is also exposed via the Ethers provider: https://docs.ethers.io/v5/api/providers/provider/#Provider-getLogs.

The syntax for the parameter is the same as for eth_newFilter.

2
  • Thank you. I did not know about this function. However, it does not seem to work. I appended the question ("Edit 2") to explain what I tried and how it failed.
    – UTF-8
    Commented Jan 20, 2022 at 14:24
  • I figured out the solution to the problem. It's a rate limiting problem by Infura. With a small specified block range, it works perfectly. Thank you! :)
    – UTF-8
    Commented Jan 20, 2022 at 15:54

Your Answer

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

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