Multicall aggregates results from multiple contract constant function calls.
This reduces the number of separate JSON RPC requests that need to be sent (especially useful if using remote nodes like Infura), while also providing the guarantee that all values returned are from the same block (like an atomic read) and returning the block number the values are from (giving them important context so that results from old blocks can be ignored if they're from an out-of-date node).
There are three contracts in this repository:
Multicall: The original contract containing anaggregatemethod to batch callsMulticall2: The same as Multicall, but provides additional functions that allow calls within the batch to fail. Useful for situations where a call may fail depending on the state of the contract.Multicall3: This is the recommended version. It's ABI is backwards compatible with Multicall and Multicall2, but it's cheaper to use (so you can fit more calls into a single request), and it adds anaggregate3method so you can specify whether calls are allowed to fail on a per-call basis. Additionally, it's deployed at every network on the same address.
These contracts can also be used to batch on-chain transactions. If using them
for this purpose, be aware these contracts are unaudited so use them at your own
risk. Additionally, make sure you understanding how msg.sender works when
calling vs. delegatecalling to a Multicall contract.
Multicall3 contains the following improvements over prior multicall contracts:
- Cheaper to use: fit more calls into a single request before hitting the RPC's
eth_callgas limit - Backwards compatible: it can be dropped in to existing code by simply changing the address
- Uses the same, memorable deployment address on all networks
If there is a network Multicall3 is not yet deployed on, please open an issue with a link to the block explorer. You can speed up the new deploy by sending funds to cover the deploy cost to the deployer account: 0x05f32B3cC3888453ff71B01135B34FF8e41263F2
Multicall3 is the recommended version for most use cases, but deployment addresses for Multicalll and Multicall2 are retained below for posterity. The Multicall smart contract was originally intended to be used with Multicall.js in front-end dapps. However, that library has not been updated to work with Multicall2 and Multicall3, so it will likely only work for the original Multicall contract.
The deployed Multicall contract can be found in commit bb309a9 or earlier. After that commit, the contract was updated to a more recent Solidity version (with minimal improvements), primarily for compatibility with the test suite.
The deployed Multicall2 contract can be found in commit bb309a9 or earlier. After that commit, the contract was updated to a more recent Solidity version (with minimal improvements), primarily for compatibility with the test suite.
Multicall2 is the same as Multicall, but provides additional functions that allow calls within the batch to fail. Useful for situations where a call may fail depending on the state of the contract.
| Chain | Address |
|---|---|
| Mainnet | 0x5ba1e12693dc8f9c48aad8770482f4739beed696 |
| Kovan | 0x5ba1e12693dc8f9c48aad8770482f4739beed696 |
| Rinkeby | 0x5ba1e12693dc8f9c48aad8770482f4739beed696 |
| Görli | 0x5ba1e12693dc8f9c48aad8770482f4739beed696 |
| Ropsten | 0x5ba1e12693dc8f9c48aad8770482f4739beed696 |
The following addresses have been submitted by external contributors and have not been vetted by Multicall maintainers.
| Chain | Address |
|---|---|
| RSK Mainnet | 0x6c62bf5440de2cb157205b15c424bceb5c3368f5 |
| RSK Testnet | 0x9e469e1fc7fb4c5d17897b68eaf1afc9df39f103 |
| BSC Mainnet | 0x41263cba59eb80dc200f3e2544eda4ed6a90e76c |
| BSC Testnet | 0xae11C5B5f29A6a25e955F0CB8ddCc416f522AF5C |
This repo uses Foundry for development and testing and git submodules for dependency management.
Clone the repo and run forge install to install dependencies and forge test to run tests.
If you don't have Foundry installed, run the command below to get foundryup, the Foundry toolchain installer:
curl -L https://foundry.paradigm.xyz | bashThen, in a new terminal session or after reloading your PATH, run foundryup to get the latest forge and cast binaries.
To learn more about Foundry:
- Visit the repo
- Check out the Foundry book
- Learn advanced ways to use
foundryupin the foundryup package - Check out the awesome-foundry repo
Below is a list of some of the optimizations used by Multicall3's aggregate3 and aggregate3Value methods:
- In for loops, array length is cached to avoid reading the length on each loop iteration
- In for loops, the counter is incremented within an
uncheckedblock - In for loops, the counter is incremented with the prefix increment (
++i) instead of a postfix increment (i++) - All revert strings fit within a single 32 byte slot
- Function parameters use
calldatainstead ofmemory - Instead of requiring
call.allowFailure || result.success, we use assembly'sor()instruction to avoid aJUMPIandiszero()since it's cheaper to evaluate both conditions - Methods are given a
payablemodifier which removes a check thatmsg.value == 0when calling a method - Calldata and memory pointers are used to cache values so they are not read multiple times within a loop
- No block data (e.g. block number, hash, or timestamp) is returned by default, and is instead left up to the caller
- The value accumulator in
aggregate3Valueis within anuncheckedblock
Read more about Solidity gas optimization tips:
