multicall.py icon indicating copy to clipboard operation
multicall.py copied to clipboard

Getting 'message': 'invalid opcode: SHR' Error while doing mutlicall with historical block number

Open ashrita-systango opened this issue 1 year ago • 1 comments

Hi,

I have written a script that takes multiple wallet/account address, token address & block number, then it prepares a multicall & call the function. For recent block numbers I get the proper result but for block number which are old like block numbers from 2017 or 2018 it gives invalid opcode SHR error. If I make the same contract function call via web3 library then it returns the result as expected.

I am getting error till block number 7256659 on ethereum.

Below is the sample code for Multicall on ETH chain:

from web3 import Web3
from web3.middleware import geth_poa_middleware
from multicall import Call, Multicall

addresses = [{'walletAddress': '0x536480A12fa7A2934872448752F864Cd0F9ba796', 'tokenAddress': '0xa74476443119a942de498590fe1f2454d7d4ac0d'}]

block_number = 4310318
GET_BALANCE_FN = "balanceOf(address)(uint256)"

def call_back_obj(success, value):
    if success is True:
        return value
    else:
        return False

node_provider = 'eth_node_provider_url'

def get_web3_instance():
    w3 = Web3(Web3.HTTPProvider(node_provider))
    w3.middleware_onion.inject(geth_poa_middleware, layer=0)
    return w3

_w3 = get_web3_instance()

def token_balance_handler(addresses, block_number=None):
    calls = []
    for address in addresses:
        contract_addr = address.get("tokenAddress")
        wallet_addr = address.get("walletAddress")
        calls.append(
            Call(
                contract_addr,
                [GET_BALANCE_FN, (wallet_addr)],
                [[f"{wallet_addr}-{contract_addr}", call_back_obj]],
            )
        )
    return Multicall(
                calls, _w3=_w3, block_id=block_number, require_success=False
            )

print(token_balance_handler(addresses, block_number)())

Sample code for contract function call via web3:

from web3 import Web3

node_provider_url = ""
# connect to Ethereum network
web3 = Web3(Web3.HTTPProvider(node_provider_url))

# set the address and ABI of the contract
contract_address = '0xa74476443119A942dE498590Fe1f2454d7D4aC0d'
contract_abi = [{'constant': True, 'inputs': [{'name': 'account', 'type': 'address'}], 'name': 'balanceOf', 'outputs': [{'name': '', 'type': 'uint256'}], 'payable': False, 'stateMutability': 'view', 'type': 'function'}]

# create a contract object
contract = web3.eth.contract(address=contract_address, abi=contract_abi)

# specify block number
block_number = 4310318

# call the balanceOf function at specific block number
account_address = '0x536480A12fa7A2934872448752F864Cd0F9ba796'
balance = contract.functions.balanceOf(account_address).call(block_identifier=block_number)

print(f'The balance of {account_address} at block {block_number} is {balance} tokens.')

ashrita-systango avatar Apr 08 '23 08:04 ashrita-systango