Introduction
Hi, I have a list of wallets and I want to ensure that a contract function is called only once. To achieve this, I iterate through the wallets, check if each wallet has already called that function, and if not, I proceed to call it. (I’m testing on Linea and Base blockchains buy I’m looking for a universal solution for EVM blockchains.)
Explanation
I need to check if a specific contract function has been called by a wallet address after a given block number. Here are the data I have:
- startblock: The block from which I want to start checking.
- contract_address: The address of the contract.
- wallet_address: The address of the wallet.
- contract_abi: The ABI of the contract.
- contract_function_name: The name of the contract function I want to check.
What I tried
Using an API to Fetch Transactions:
I used the Lineascan/Basescan API to fetch transactions with the following code:
url = (f"{self.scan_api_url}"
f"?module=account"
f"&action=txlist"
f"&address={wallet_address if wallet_address is not None else self.wallet_address}"
f"&startblock={self.quest.start_block}"
f"&endblock=99999999"
f"&page=1"
f"&offset=10000"
f"&sort=asc"
f"&apikey={self.scan_api_key}")
And checking for contract_address on the list.
However, this approach often fails to return recent blocks due to delays in the API.
Iterating Through Blocks:
I tried iterating from the latest block back to startblock and checking for wallet_address.
block = self.w3.eth.get_block(block_num, full_transactions=True)
This method is very slow because it processes a large number of blocks.
Using get_logs():
I attempted to use the get_logs() method but faced limitations:
logs = self.w3.eth.get_logs()
The method has a limit of 1000 blocks and I couldn’t figure out how to filter by wallet address and contract function.
What I’m Looking For:
Preferred Solution: A way to efficiently check if wallet_address has called contract_function_name on contract_address after start_block. Ideally, this solution would filter by both wallet address and contract function.
Alternative Solution: If filtering by both wallet address and contract function is not feasible, a solution that simply checks if wallet_address interacted with contract_address would be acceptable.
Any help or guidance on how to achieve this efficiently would be greatly appreciated!