0

Let's take this contract as an example: 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c.

It has multiple methods / properties that I wish to access, e.g.

function name() public view returns (string memory) {
    return _name;
}

function symbol() public view returns (string memory) {
    return _symbol;
}

function decimals() public view returns (uint8) {
    return _decimals;
}

function totalSupply() public view override returns (uint256) {
    return _tTotal;
}

At the moment, it seems like I need to call all of them individually, e.g.

await pairContract.methods.name().call()
await pairContract.methods.symbol().call()
await pairContract.methods.decimals().call()
await pairContract.methods.totalSupply().call()

Is there a way to retrieve all of the above in a single call to limit the number of roundtrips / requests?

I have found that there is BatchRequest, but from what I can tell, it is equivalent to:

[
  pairContract.methods.name().call(),
  pairContract.methods.symbol().call(),
  pairContract.methods.decimals().call(),
  pairContract.methods.totalSupply().call()
]

i.e. it does not actually batch the requests.

2 Answers 2

1

To answer my own question: Yes, you can, thanks to multicall smart contract and ethereum-bsc-multicall SDK.

It would look something like this:

const contractCallContext: ContractCallContext[] = [
  {
    abi: BEP20_ABI,
    calls: [
      {
        methodName: 'name',
        reference: 'name',
      },
      {
        methodName: 'symbol',
        reference: 'symbol',
      },
      {
        methodName: 'decimals',
        reference: 'decimals',
      },
      {
        methodName: 'totalSupply',
        reference: 'totalSupply',
      },
    ],
    contractAddress: '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c',
    reference: 'summary',
  },
];

const findResultValue = (callsReturnContext, reference) => {
  return callsReturnContext.find((result) => {
    return result.reference === reference;
  })?.returnValues?.[0];
};

const response = await multicall.call(contractCallContext);

console.log({
  decimals: findResultValue(response.results.summary.callsReturnContext, 'decimals'),
  name: findResultValue(response.results.summary.callsReturnContext, 'name'),
  symbol: findResultValue(response.results.summary.callsReturnContext, 'symbol'),
  totalSupply: findResultValue(response.results.summary.callsReturnContext, 'totalSupply'),
});

which produces result such as:

{
  decimals: 18,
  name: 'Wrapped BNB',
  symbol: 'WBNB',
  totalSupply: { type: 'BigNumber', hex: '0x067463bb2aa7d7bc4ea935' }
}
1

If you are looking for an example in JS see https://github.com/indexed-finance/multicall.

const ethers = require('ethers');
const { MultiCall } = require('@indexed-finance/multicall');

async function getMultiCallResults(tokenAbi, provider){
  let tokenAddress = '0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c';
  
  const multi = new MultiCall(provider);
  const callParams = [
      {target: tokenAddress, function: 'name', args: []},
      {target: tokenAddress, function: 'symbol', args: []}
      .......
  ];
  const tokenDatas = await multi.multiCall(tokenAbi, callParams);
  console.log(tokenDatas[1][0].toString()); // name
  console.log(tokenDatas[1][1].toString()); // symbol
  ......
}

Here you can find a full explanation of how multicall libraries work https://blockheroes.dev/same-block-data-querying/.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.