RZND8 / multicall

Multicall: Aggregate multiple constant function call results into one

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Multicall • tests GitHub

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 an aggregate method to batch calls
  • Multicall2: 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 an aggregate3 method so you can specify whether calls are allowed to fail on a per-call basis. Additionally, it's deployed on every network at 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 understand how msg.sender works when calling vs. delegatecalling to the Multicall contract, as well as the risks of using msg.value in a multicall. To learn more about the latter, see here and here.

You can obtain the ABI for the Multicall contracts in the following ways:

  • Download the ABI from the releases page
  • Copy the ABI from Etherscan
  • Install Foundry and run cast interface 0xcA11bde05977b3631167028862bE2a173976CA11
  • Copy the human-readable ABI below for use with ethers.js.

Deployments

Multicall3 Contract Addresses

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_call gas limit.
  • Backwards compatible: it can be dropped in to existing code by simply changing the address.
  • Uses the same, memorable deployment address on the 50+ networks it's deployed to.
Chain Chain ID Address
Mainnet 1 0xcA11bde05977b3631167028862bE2a173976CA11
Kovan 42 0xcA11bde05977b3631167028862bE2a173976CA11
Rinkeby 4 0xcA11bde05977b3631167028862bE2a173976CA11
Görli 5 0xcA11bde05977b3631167028862bE2a173976CA11
Ropsten 3 0xcA11bde05977b3631167028862bE2a173976CA11
Sepolia 11155111 0xcA11bde05977b3631167028862bE2a173976CA11
Optimism 10 0xcA11bde05977b3631167028862bE2a173976CA11
Optimism Kovan 69 0xcA11bde05977b3631167028862bE2a173976CA11
Optimism Görli 420 0xcA11bde05977b3631167028862bE2a173976CA11
Arbitrum 42161 0xcA11bde05977b3631167028862bE2a173976CA11
Arbitrum Nova 42170 0xcA11bde05977b3631167028862bE2a173976CA11
Arbitrum Görli 421613 0xcA11bde05977b3631167028862bE2a173976CA11
Arbitrum Rinkeby 421611 0xcA11bde05977b3631167028862bE2a173976CA11
Polygon 137 0xcA11bde05977b3631167028862bE2a173976CA11
Mumbai 80001 0xcA11bde05977b3631167028862bE2a173976CA11
Gnosis Chain (xDai) 100 0xcA11bde05977b3631167028862bE2a173976CA11
Avalanche 43114 0xcA11bde05977b3631167028862bE2a173976CA11
Avalanche Fuji 43113 0xcA11bde05977b3631167028862bE2a173976CA11
Fantom Testnet 4002 0xcA11bde05977b3631167028862bE2a173976CA11
Fantom Opera 250 0xcA11bde05977b3631167028862bE2a173976CA11
BNB Smart Chain 56 0xcA11bde05977b3631167028862bE2a173976CA11
BNB Smart Chain Testnet 97 0xcA11bde05977b3631167028862bE2a173976CA11
Moonbeam 1284 0xcA11bde05977b3631167028862bE2a173976CA11
Moonriver 1285 0xcA11bde05977b3631167028862bE2a173976CA11
Moonbase Alpha Testnet 1287 0xcA11bde05977b3631167028862bE2a173976CA11
Harmony 1666600000 0xcA11bde05977b3631167028862bE2a173976CA11
Cronos 25 0xcA11bde05977b3631167028862bE2a173976CA11
Fuse 122 0xcA11bde05977b3631167028862bE2a173976CA11
Flare Mainnet 14 0xcA11bde05977b3631167028862bE2a173976CA11
Songbird Canary Network 19 0xcA11bde05977b3631167028862bE2a173976CA11
Coston Testnet 16 0xcA11bde05977b3631167028862bE2a173976CA11
Coston2 Testnet 114 0xcA11bde05977b3631167028862bE2a173976CA11
Boba 288 0xcA11bde05977b3631167028862bE2a173976CA11
Aurora 1313161554 0xcA11bde05977b3631167028862bE2a173976CA11
Astar 592 0xcA11bde05977b3631167028862bE2a173976CA11
OKC 66 0xcA11bde05977b3631167028862bE2a173976CA11
Heco Chain 128 0xcA11bde05977b3631167028862bE2a173976CA11
Metis 1088 0xcA11bde05977b3631167028862bE2a173976CA11
RSK 30 0xcA11bde05977b3631167028862bE2a173976CA11
RSK Testnet 31 0xcA11bde05977b3631167028862bE2a173976CA11
Evmos 9001 0xcA11bde05977b3631167028862bE2a173976CA11
Evmos Testnet 9000 0xcA11bde05977b3631167028862bE2a173976CA11
Thundercore 108 0xcA11bde05977b3631167028862bE2a173976CA11
Thundercore Testnet 18 0xcA11bde05977b3631167028862bE2a173976CA11
Oasis 42262 0xcA11bde05977b3631167028862bE2a173976CA11
Celo 42220 0xcA11bde05977b3631167028862bE2a173976CA11
Celo Alfajores Testnet 44787 0xcA11bde05977b3631167028862bE2a173976CA11
Godwoken 71402 0xcA11bde05977b3631167028862bE2a173976CA11
Godwoken Testnet 71401 0xcA11bde05977b3631167028862bE2a173976CA11
Klaytn 8217 0xcA11bde05977b3631167028862bE2a173976CA11
Milkomeda 2001 0xcA11bde05977b3631167028862bE2a173976CA11
KCC 321 0xcA11bde05977b3631167028862bE2a173976CA11
Velas 106 0xcA11bde05977b3631167028862bE2a173976CA11
Telos 40 0xcA11bde05977b3631167028862bE2a173976CA11
Step Network 1234 0xcA11bde05977b3631167028862bE2a173976CA11
Canto 7700 0xcA11bde05977b3631167028862bE2a173976CA11
Iotex 4689 0xcA11bde05977b3631167028862bE2a173976CA11
Bitgert 32520 0xcA11bde05977b3631167028862bE2a173976CA11

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

Historical Deployments

Multicall3 is the recommended version for most use cases, but deployment addresses for Multicall 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.

Multicall Contract Addresses

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.

Chain Address
Mainnet 0xeefba1e63905ef1d7acba5a8513c70307c1ce441
Kovan 0x2cc8688c5f75e365aaeeb4ea8d6a480405a48d2a
Rinkeby 0x42ad527de7d4e9d9d011ac45b31d8551f8fe9821
Görli 0x77dca2c955b15e9de4dbbcf1246b4b85b651e50e
Ropsten 0x53c43764255c17bd724f74c4ef150724ac50a3ed
xDai 0xb5b692a88bdfc81ca69dcb1d924f59f0413a602a
Polygon 0x11ce4B23bD875D7F5C6a31084f55fDe1e9A87507
Mumbai 0x08411ADd0b5AA8ee47563b146743C13b3556c9Cc
Optimism 0x187C0F98FEF80E87880Db50241D40551eDd027Bf
Arbitrum 0xB064Fe785d8131653eE12f3581F9A55F6D6E1ca3

Multicall2 Contract Addresses

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

Third-Party Deployments

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

Development

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.

Foundry Setup

If you don't have Foundry installed, run the command below to get foundryup, the Foundry toolchain installer:

curl -L https://foundry.paradigm.xyz | bash

Then, 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:

Gas Golfing Tricks and Optimizations

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 unchecked block
  • 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 calldata instead of memory
  • Instead of requiring call.allowFailure || result.success, we use assembly's or() instruction to avoid a JUMPI and iszero() since it's cheaper to evaluate both conditions
  • Methods are given a payable modifier which removes a check that msg.value == 0 when 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 aggregate3Value is within an unchecked block

Read more about Solidity gas optimization tips:

Human-Readable ABI

Below is the human-readable ABI. This can be directly passed into an ethers.js Contract or Interface constructor.

const MULTICALL_ABI = [
  // https://github.com/mds1/multicall
  'function aggregate(tuple(address target, bytes callData)[] calls) payable returns (uint256 blockNumber, bytes[] returnData)',
  'function aggregate3(tuple(address target, bool allowFailure, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)',
  'function aggregate3Value(tuple(address target, bool allowFailure, uint256 value, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)',
  'function blockAndAggregate(tuple(address target, bytes callData)[] calls) payable returns (uint256 blockNumber, bytes32 blockHash, tuple(bool success, bytes returnData)[] returnData)',
  'function getBasefee() view returns (uint256 basefee)',
  'function getBlockHash(uint256 blockNumber) view returns (bytes32 blockHash)',
  'function getBlockNumber() view returns (uint256 blockNumber)',
  'function getChainId() view returns (uint256 chainid)',
  'function getCurrentBlockCoinbase() view returns (address coinbase)',
  'function getCurrentBlockDifficulty() view returns (uint256 difficulty)',
  'function getCurrentBlockGasLimit() view returns (uint256 gaslimit)',
  'function getCurrentBlockTimestamp() view returns (uint256 timestamp)',
  'function getEthBalance(address addr) view returns (uint256 balance)',
  'function getLastBlockHash() view returns (bytes32 blockHash)',
  'function tryAggregate(bool requireSuccess, tuple(address target, bytes callData)[] calls) payable returns (tuple(bool success, bytes returnData)[] returnData)',
  'function tryBlockAndAggregate(bool requireSuccess, tuple(address target, bytes callData)[] calls) payable returns (uint256 blockNumber, bytes32 blockHash, tuple(bool success, bytes returnData)[] returnData)',
];

About

Multicall: Aggregate multiple constant function call results into one

License:MIT License


Languages

Language:Solidity 100.0%