mds1 / multicall

Multicall: Aggregate multiple constant function call results into one
https://multicall3.com
MIT License
933 stars 161 forks source link

Arbitrum multicall3 contract returning Ethereum blockNumber #138

Closed mozzy02 closed 1 year ago

mozzy02 commented 1 year ago

Issue Description

When calling the getBlockNumber() method on the multicall3 contract on the Arbitrum chain, the value returned appears to be for the Ethereum chain.

I did test this on a few other chains (non-exhaustive) and the getBlockNumber() seems to work as expected on those with the exception of the testnet Arbitrum Goerli.

Environment tested in:

Issue Replication

Run the test script below, replacing ARBITRUM_RPC_PROVIDER_URL and ETHEREUM_RPC_PROVIDER_URL with valid RPC provider URLs. One should witness:

Test script:

'use strict';

const ethers = require('ethers');

const MULTICALL3_ADDRESS = '0xcA11bde05977b3631167028862bE2a173976CA11';
const MULTICALL2_ARBITRUM_ADDRESS = '0x842eC2c7D803033Edf55E478F461FC547Bc54EB2';
const MULTICALL_MIN_ABI = [{
    "inputs":[

    ],
    "name":"getBlockNumber",
    "outputs":[
      {
        "internalType":"uint256",
        "name":"blockNumber",
        "type":"uint256"
      }
    ],
    "stateMutability":"view",
    "type":"function"
}];

const ARBITRUM_RPC_PROVIDER_URL = '';
const ETHEREUM_RPC_PROVIDER_URL = '';

async function test () {
    const ArbitrumProvider = new ethers.JsonRpcProvider(ARBITRUM_RPC_PROVIDER_URL);
    const multicall3Contract = new ethers.Contract(MULTICALL3_ADDRESS, MULTICALL_MIN_ABI, ArbitrumProvider);
    const multicall2Contract = new ethers.Contract(MULTICALL2_ARBITRUM_ADDRESS, MULTICALL_MIN_ABI, ArbitrumProvider);

    const EthereumProvider = new ethers.JsonRpcProvider(ETHEREUM_RPC_PROVIDER_URL);

    const [arbBlockNumberMulti3, arbBlockNumberMulti2, arbBlockNumberProvider, ethBlockNumberProvider] = await Promise.all([
        multicall3Contract.getBlockNumber(),
        multicall2Contract.getBlockNumber(),
        ArbitrumProvider.getBlockNumber(),
        EthereumProvider.getBlockNumber(),
    ]);

    console.log(`Arbitrum block number from multicall3: ${arbBlockNumberMulti3}`);
    console.log(`Arbitrum block number from multicall2: ${arbBlockNumberMulti2}`);
    console.log(`Arbitrum block number from provider: ${arbBlockNumberProvider}`);
    console.log(`Ethereum block number from provider: ${ethBlockNumberProvider}`);
}

test().catch(console.error);
mds1 commented 1 year ago

Hey! Yes this is the expected behavior as this is an Arbitrum design decision. You can read more on EVM Diff here—check out the NUMBER opcode and the listed references. This reference will tell you how to access the arbitrum block number