question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Multicall context manager

See original GitHub issue

Overview

Brownie should offer first-class support for multicall via a context manager:

with multicall:
    a = foo.bar()
    b = foo.barfoo()
    c = bar.foobar(a)
    d = bar.otherbar()

Specification

While the context manager is open, a middleware intercepts all eth_call requests and returns objects which represent the result of the call once it completes. When the context manager closes, or there is an attempt to use one of the pending call objects, a single multicall is made to get the actual values.

In the above example a and b would end up joined as a single multicall that executes when a is needed for c. Then c and d would happen as a multicall when the context manager exits.

We can bundle the MultiCall2 implementation as used by yearn, which uses try/catch to prevent calls from failing. Attempting to interact with object for the specific result that failed in the multicall should raise a ValueError. (Or possibly the object simply returns None? Maybe this behavior is determined via a kwarg in the context manager?)

It is important to consider thread safety during the implementation. The context manager must introspect to be aware of which thread it is running on, and not also batch eth_call operations coming from unrelated threads.

To ensure consistent behaviour across network, we can use Geth’s state override feature to simulate the existence of a multicall contract for the purposes of the call. This is badass in so many ways I’m not even sure where to begin 😈 For dev networks where this isn’t possible, deploy multicall silently the first time it’s required.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:3
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
omarishcommented, Mar 25, 2021

For sure.

I think a clean implementation would have at least two pieces: a private function to commit a single transaction block (like scenario A above), and then something higher level (probably public) that calls that function every time (1) the multicall needs to be executed, and (2) when the context manager __exit__s.

Perhaps something like this:

def _exec_multicall(*args, **kwargs):
   # used to run a series of calls and will error out 

@contextmanager
def multicall(*args, **kwargs):
   # this is the actual context manager that's exposed, it has some logic and uses `_exec_multicall` for batches.

We could start with the simplest thing, which would be the context manager as initially proposed, then we could see how it feels and go from there. How does that sound?

0reactions
iamdefinitelyahumancommented, Jul 19, 2021

Implemented in #1125

Read more comments on GitHub >

github_iconTop Results From Across the Web

banteg on Twitter: "Brownie update - Multicall context ...
Brownie update - Multicall context manager - Hardware wallet support via Clef - EIP712 message signing - Solidity 0.8 typed errors - Vyper...
Read more >
Multicall Requests - by BowTiedDevil - Degen Code - Substack
The multicall context manager was built with awareness that batched calls cannot be executed when they grow too large.
Read more >
@0xsequence/multicall - npm
An Ethereum provider wrapper that aggregates multiple operations in one, reducing the network load on clients and servers. The project aims to ...
Read more >
Network API — Brownie 1.16.1 documentation - Read the Docs
The multicall module contains the Multicall context manager, which allows for the batching of multiple constant contract function calls via Multicall2 .
Read more >
xmlrpc.client — XML-RPC client access — Python 3.11.1 ...
Changed in version 3.5: Instances of ServerProxy support the context manager protocol for closing the underlying transport. A working example follows.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found