Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: automatically batch consecutive eth_calls with a multicall #2508

Open
mds1 opened this issue Jul 12, 2023 · 4 comments · May be fixed by #2684
Open

feat: automatically batch consecutive eth_calls with a multicall #2508

mds1 opened this issue Jul 12, 2023 · 4 comments · May be fixed by #2684

Comments

@mds1
Copy link

mds1 commented Jul 12, 2023

Is your feature request related to a problem? Please describe.
viem has a really nice feature where consecutive calls are held in a queue then automatically batched using Multicall3. As you can see from the docs, this enables really nice UX such as:

const contract = getContract({ address, abi })

// The below will send a single request to the RPC Provider.
const [name, totalSupply, symbol, tokenUri, balance] = await Promise.all([
  contract.read.name(),
  contract.read.totalSupply(),
  contract.read.symbol(),
  contract.read.tokenURI([420n]),
  contract.read.balanceOf([address]),
])

This UX is much better than manually configuring the multicall. And a multicall results in significantly better performance and reduced RPC bills compared to individual calls

The other motivation for asking this is related to upstream usage in foundry. When users write forge tests or scripts, they'll often make many view calls to fetch data from the chain. Currently each call is a single RPC request, so you quickly end up with a lot of RPC calls, resulting in throttling and slower tests.

Supporting this feature and leveraging it in forge can result in significantly faster fork tests and scripts.

Describe the solution you'd like
I'm not sure how feasible a viem-like solution is in rust, but that's the ideal solution here: abstract away the need for users to worry about multicall but automatically batching calls, e.g. the below should be a single RPC call:

// Currently the below snippet would send 5 RPC requests to the provider, but ideally
// it should just send a single multicall request.
let (name, total_supply, symbol, token_uri, balance) = tokio::try_join!(
    contract.method::<_, String>("name", (), None)?.call(),
    contract.method::<_, U256>("totalSupply", (), None)?.call(),
    contract.method::<_, String>("symbol", (), None)?.call(),
    contract.method::<_, String>("tokenURI", (U256::from(420),), None)?.call(),
    contract.method::<_, U256>("balanceOf", (contract_address,), None)?.call(),
)?;

Describe alternatives you've considered
Explicit multicall batching is the main alternative

Additional context
Idea came out of a convo in foundry support telegram: https://t.me/foundry_support/40543

@yorhodes
Copy link

yorhodes commented Nov 17, 2023

I would like to work on this

This UX is much better than manually configuring the multicall.

Motivated by this exact pain point in our already large codebase

@yorhodes yorhodes linked a pull request Nov 22, 2023 that will close this issue
3 tasks
@yorhodes
Copy link

hey @mds1, happy to report I have completed the implementation in #2684 supporting the ideal DX you describe

@yorhodes
Copy link

should probably mirror the config options here https://viem.sh/docs/clients/public.html#batch-multicall-optional

@HenriBrg
Copy link

Hey, looking also for the RPC batch request feature in Rust, is there a new solution available since opening this issue/PR ? TY

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants