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