multicall.py
multicall.py copied to clipboard
Getting 'message': 'invalid opcode: SHR' Error while doing mutlicall with historical block number
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.')