ethers.js icon indicating copy to clipboard operation
ethers.js copied to clipboard

Optimize functions like Viem ( Multicall, Provider, ENS, Events )

Open cpuchainorg opened this issue 6 months ago • 3 comments

Describe the Feature

Hello,

I have created ethers-opt that could bring some optimization features that Viem offers.

For example)

1. Viem aggregates eth_call requests to multicall3 by default https://viem.sh/docs/clients/custom#batchmulticall-optional and the feature is also implemented with ext-provider-multicall for ethers v6 however it is not available by default.

I have made Provider class inside ethers-opt library to make it default https://github.com/cpuchain/ethers-opt/blob/main/src/provider.ts#L304. ( So that any contract reads batched by Promise.all will be automatically included inside a single or two multicall requests which also makes possible to fetch 1K ERC20 balances in a single call for example. )

2. Viem uses Universal Resolver which should be used by default cause it not only allows to do recursive calls for resolving ENS records ( like finding resolver for a specific name -> looking up records would be done in a single call within universal resolver which makes possible to lookup multiple records or multiple names within a single eth_call, think that what would be possible when combined with the multicaller )

3. Static network should be default and it should not consume additional CUs by calling eth_chainId for every request.

I have solved this by making it a cached promise on https://github.com/cpuchain/ethers-opt/blob/main/src/provider.ts#L144

4. maxFeePerGas value shouldn't be a 2x value of block.baseFee and the multiplier value should be always configurable

I have overridden provider.getFeeData() to expose the base fee of block as is ( https://github.com/cpuchain/ethers-opt/blob/main/src/provider.ts#L209 ) and configured multiplier ( https://github.com/cpuchain/ethers-opt/blob/main/src/signer.ts#L92C72-L92C85 ) because fee calculations shouldn't be multiplied otherwise it would break or over-estimate when it comes to build something like Paymasters of how many fees should be paid, etc.

5. eth_getLogs params should be much easier for use and should be allowed to batch those in chunks

Because most RPC providers would limit block ranges chunking requests is inevitable and ethers.js should export params / necessary functions for batching and make it easier for use.

For example I have copy-pasted all those necessary functions from ethers.js because they are not exported https://github.com/cpuchain/ethers-opt/blob/main/src/ethers.ts#L61 and should be exported and allowed to be overritten.

Also chunks / batching should be possible with further optimized functions for an easier indexing like how those rust indexers offers right now.

6. Add functions to decode / type internal transactions

There are only like 2 ~ 3 common methods to fetch internal calls and I have made the temporary functions / type definitions. https://github.com/cpuchain/ethers-opt/blob/main/src/traceBlock.ts However I believe that ethers could support those by default because you only need to type those from either Geth or Erigon to do it.

7. Discovering multiple EIP-6963 Browser Providers

Currently only a single random browser injected wallets would be detected but what if multiple wallets are installed?

https://github.com/cpuchain/ethers-opt/blob/main/src/browserProvider.ts#L131

So that is why I have it here

8. eth_getBlockReceipts

https://github.com/cpuchain/ethers-opt/blob/main/src/blockReceipts.ts

9. Some simple reorg solution

Ether noobs wouldn't be able to code reorg handler easily and I have made some simple function to do it https://github.com/cpuchain/ethers-opt/blob/main/src/blockHashes.ts,

Maybe there should be some function provided by ethers it would be great

10. Support Permit / Permit2

Instead of expecting people to understand how to handle signatures using Permit / Permit2 could be done at the simplest form with the following https://github.com/cpuchain/ethers-opt/blob/main/src/permit.ts#L7

11. Static ENS resolvers / Expecting wildcard resolvers

Instead of sending 3~5 requests to fetch redundant data why we can not hardcode those if 99% of cases are covered and do only fallbacks for custom resolvers

https://github.com/cpuchain/ethers-opt/blob/main/src/ens/eth.ts#L55

With some care those functions and features can be easily implemented, however if not it would simply drain CUs and RPC credits and make DApps slower to use since nodes are slow and waiting those requests for a simple task would be even more slower.

@ricmoo Maybe it would be great when I no longer need to maintain additional package with those simple issues being optimized and fixed.

Code Example

https://github.com/cpuchain/ethers-opt

cpuchainorg avatar Jun 20 '25 13:06 cpuchainorg

Heya!!

Thanks for the message/package. Sorry it's take so long to respond, I wanted to make sure I had time to command and address all the points. And EthCC prep has been busy too. If you are around Cannes, feel free to come say hi. :)

  1. The main issue with multicall, and why it isn't used by default is that it returns "wrong data" in specific cases (i.e. msg.sender is the multi call contract, not the caller. These cases for getters often aren't an issue, but since static calls can be used on setters too, the results can cause serious harm. So, using multi call must be opt-in. One feature of the Ethers multisite though is that it doesn't rely on a deployed contract, it uses deployment-less instantiation.
  2. This is absolutely coming, and I will be looking at your code extensively to help out. Thanks! :)
  3. I agree, and have debated for a long time whether it is a safe change to make without a major version bump. I do worry that there may exist code that depends on it, but I do think it unlikely. I am very close to biting the bullet and making that change.
  4. I'll look into that; it was based on the advice at the time that EIP-1559 was put in place. It will require extensive testing thought before I make that change, and I'll schedule a talk with the AA guys to get their opinion. Anyone else (yourself included) that would like to chat about it, let me know.
  5. Thanks! I have to look more into this, but if there are better APIs for logs, I'm all for it. :)
  6. Are trace APIs widely enabled? I had always assumed sub-classes would arise (and for example, could be added to specific providers that extend debugging capabilities, like if AlchemyProvider has extra features). Again, I'll look more into it and see how widely adopted those APIs are. Any links are appreciated. :)
  7. I need to provide a code snippet on how to use the current API to detect multiple wallets, and there are some extensions to the filter API I plan on. But I wanted to get an initial version out to make life easier.
  8. I'll look into this. :)
  9. Thanks! I've been planning re-org filters for a long time, and have preliminary support, but since proof-of-stake, that has definitely taken a back-burner. Are there ever still any re-orgs on mainnet? Or is it mainly for PoW chains this affects?
  10. In general, I'd love to see a common-contracts package, which rolls up many of the most common contracts into pre-typed, ready to go (with extra useful utility functions; like "computeCommithash"). If anyone wants to help spearhead that, please reach out, I can set up a repo on ethers-io org for it and get the ball rolling with a few simple examples.
  11. I'll look into this too; there will probably be a few changes that go along with the UniversalResolver.

Ok, I think that is my preliminary response. Please feel free to keep the back and forth going, and would love to schedule a call sometime too, if you want to dive into anything deeper.

Marking this as in-progress, but I might also split it up into multiple issues. Or try that new "sub-issue" feature.

Thanks!

ricmoo avatar Jul 05 '25 10:07 ricmoo

  1. Yes that is why I have added filter if there is "from" tag it wouldn't be included for batch

https://github.com/cpuchain/ethers-opt/blob/main/src/provider.ts#L447

I wouldn't mind if MulticallProvider is a separate class, but I think it should be inheritable for existing providers like JsonRpcProvider and most importantly it should be in the same package ( ethers ) so that it would be ensured to be maintained at a regular basis

  1. Yes ENS is a first class citizen of ethers and I think having inefficient ens implementation for ethers isn't a good thing so I think it must be fixed

  2. This is must have, I don't think there would be any projects that relies on dynamic network object or if there are there is a serious problem with their node connection in a hacky way.

  3. I don't think it is a proper advice from them but if to make justification to overcharge people with unnecessary fees then...

  4. Yes batching logs is a must now due to how nodes limit block ranges :(

  5. There are standardized because of how Erigon, Reth, and Geth supports same RPC method with same return types, other providers would have to follow if not for customization.

  6. To make life easier I would suggest detecting multiple wallets with a single function call without adding much listeners on DOM

  7. :)

  8. Reorgs are common not only for ETH but also for PoS chains like polygon https://www.reddit.com/r/0xPolygon/comments/10bvruq/polygons_block_reorg_problem_daily_10_depth_reorgs/

You could also refer ETHEREUM_REORG_THRESHOLD=250 value for graph node which is used to sync subgraphs https://github.com/graphprotocol/graph-node

  1. Ofc, but I think it would make sense to add some extra functions to sign common EIP-712 types without making another dependencies

  2. This is not so hard task and think that it would make sense to expand hardcoded value with common configs provided by name service providers, I think you could ask ENS and Base for it.

cpuchainorg avatar Jul 07 '25 08:07 cpuchainorg

And I would like to suggest checking out issue https://github.com/ethers-io/ethers.js/issues/5011, instead of calling block headers for every logs synced just to find out utc timestamp of the emitted logs this would reduce up to 90% of the calls required to sync events and could only require single eth_getLogs call for projects.

cpuchainorg avatar Jul 07 '25 08:07 cpuchainorg