Trying to retrieve specific contract source code, in bulk, from Etherscan's API. Python

36 views Asked by At

I would like to get the source code for all Ethereum contracts that ran out of gas, or at least a few thousand contracts and their transactions (given my current FREE API service limitations). I tried the following code to get the log of failed transactions due to an out-of-gas error, but it gets stuck running and nothing prints out. What else can I do to get this data, is it doable with the code I am trying with?

import time
import requests

# Define the base URL for the Etherscan API
base_url = 'https://api.etherscan.io/api'

# Define parameters for the API request
params = {
    'module': 'logs',
    'action': 'getLogs',
    'fromBlock': '0',
    'toBlock': 'latest',
    'address': '',  # Leave empty to retrieve all transactions
    'topic0': '',  # Define your topics if needed
    'apikey': 'XXXXXXXXXXXXX'
}


# Function to make API request and handle rate limits
def make_api_request(url, params):
    while True:
        response = requests.get(url, params=params)
        data = response.json()
        if 'error' in data:
            print(f"Error: {data['error']['message']}")
            if data['error']['message'] == 'Max rate limit reached':
                print("Waiting for 1 second before retrying...")
                time.sleep(1)
                continue  # Retry after waiting
        return data


# Function to fetch contract source code
def fetch_contract_source_code(contract_address):
    url = f'https://api.etherscan.io/api?module=contract&action=getsourcecode&address={contract_address}&apikey=XXXXXXXXXXXXX'
    response = requests.get(url)
    data = response.json()
    if data['status'] == '1' and data['result']:
        return data['result'][0]['SourceCode']
    else:
        return "Contract source code not available"


    # Open a text file for writing
    with open("output.txt", "w") as output_file:
    # Iterate over blocks
    block_number = 0  # Start from block 0
    api_calls = 0
    while True:
        params['fromBlock'] = str(block_number)
        data = make_api_request(base_url, params)
        api_calls += 1

        if 'result' in data:
            # Process transactions in the block
            for log_entry in data['result']:
                if isinstance(log_entry, dict) and log_entry.get('status') == '0' and       log_entry.get(
                        'gasUsed') == log_entry.get('gas'):
                    output_file.write(f"Failed transaction:       {log_entry['transactionHash']}\n")
                    contract_address = log_entry.get('address')
                    if contract_address:
                        contract_source_code = fetch_contract_source_code(contract_address)
                        output_file.write(f"Contract Source  Code:\n{contract_source_code}\n")
            block_number += 1
        else:
            output_file.write("No more blocks to process.\n")
            break
0

There are 0 answers